使用并行执行策略使用for_each在stl vector上迭代时,获取给定元素的索引的最佳方法是什么?

发布于 2025-01-21 20:28:28 字数 967 浏览 0 评论 0原文

在这样的代码中:

std::for_each(std::execution::par, Vals.begin(), Vals.end(), [&](const MyType& val) {
    Other[ind] = f(val); // ind should be the index of val in Vals.
});

获得值IND的最佳方法是什么?

这与以下问题相似:

  • 每个“ > An-STDDECTOR的to-get-the-interator'>获得std :: vector迭代器索引的最有效方法是什么?

但是讨论的主要解决方案在这些问题中,这里不起作用:

it - Vals.begin()

我没有迭代器。

std::distance(Vals.begin(), it)

再次,没有迭代器。

在for_each案例中,具有单独的循环计数器变量不起作用。

我发现的解决方案是:

size_t ind = &val - &(*Vals.begin());

但这感觉就像是针对语言而不是使用它。这也有点容易发生且不远。有更好的东西吗?

顺便说一句,这个问题是否得到了很好的理解和赞赏?我每天面对几次。我觉得我在一个容器上迭代的时间超过一半,而不仅仅是数据,而不仅仅是数据。和基于范围的for和std :: for_each根本没有任何帮助。

编辑:当我说“容易出错”时,我的主要关注点是编译器在调用语言时可能会选择在堆栈上制作val副本。由于Val为const,这将是可以接受的。但是在那种情况下,瓦尔的指针不会在数组中,因此减去&*vals.begin()是非常错误的。该语言是否允许这样的编译器实现,或者我们能确定要在Val内部使用的指针?

In code such as this:

std::for_each(std::execution::par, Vals.begin(), Vals.end(), [&](const MyType& val) {
    Other[ind] = f(val); // ind should be the index of val in Vals.
});

What is the best way to get the value ind?

This is similar to these questions:

But the main solutions discussed in those questions don't work here:

it - Vals.begin()

I don't have an iterator.

std::distance(Vals.begin(), it)

Again, no iterator.

And having a separate loop counter variable doesn't work in the parallel for_each case.

The solution I've found is this:

size_t ind = &val - &(*Vals.begin());

But this feels like working against the language instead of with it. It's also a bit error prone and inelegant. Is there something better?

As an aside, is this issue well understood and appreciated? I face this several times a day. I feel like way more than half the time that I'm iterating over a container I need the index, not just the data. And range-based for and std::for_each are just no help at all.

EDIT: When I say "error prone", my main concern is that a compiler might choose to make a copy of val on the stack when calling the language. This would be semantically acceptable since val is const. But in that case, the pointer to val would not be in the array, so subtracting &*Vals.begin() would be very wrong. Does the language allow such a compiler implementation, or can we know for sure that a pointer to val will be inside Vals?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不念旧人 2025-01-28 20:28:28

如果此不高度公式会困扰您,则可以将原始值范围转换为一系列迭代器,以便您可以直接在lambda中获取迭代器来计算索引并通过operator*()<()< /code>

auto ValIters = std::views::iota(Vals.begin(), Vals.end());
std::for_each(std::execution::par, ValIters.begin(), ValIters.end(), 
  [&](auto iter) {
    Other[iter - Vals.begin()] = f(*iter);
  });

demo

当前C ++ 20 &lt; a href =“ https://stackoverflow.com/a/71588682/11638718”>无法正常工作使用C ++ 17并行算法,但是如果您使用libstdc ++,我认为上面的示例可以很好地示例,尽管它并不是严格化的。

借助C ++ 23 view /a>,我们可以直接写作

ranges::for_each(std::execution::par, views::enumerate(Vals), [&](auto e) {
  auto [index, value] = e;
  Other[index] = f(value);
});

If this inelegant formula bothers you, you can transform the original range of values into a range of iterators, so that you can get the iterator directly in the lambda to calculate the index and get the underlying type through operator*()

auto ValIters = std::views::iota(Vals.begin(), Vals.end());
std::for_each(std::execution::par, ValIters.begin(), ValIters.end(), 
  [&](auto iter) {
    Other[iter - Vals.begin()] = f(*iter);
  });

Demo

While currently C++20 <ranges> does not work well with C++17 parallel algorithms, but if you're using libstdc++, I think the above example is fine, although it's not strictly well-formed.

With the help of C++23 views::enumerate, we can write directly like this

ranges::for_each(std::execution::par, views::enumerate(Vals), [&](auto e) {
  auto [index, value] = e;
  Other[index] = f(value);
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文