如何在没有迭代器的情况下使用 std::for_each + std::execution::p ar?

How to use std::for_each + std::execution::par without iterator?

本文关键字:std for each execution ar 迭代器 情况下      更新时间:2023-10-16

我想使用std::for_each(std::execution::par, ...)tbb::parallel_for风格。

tbb::parallel_for(0, n, [](const tbb::blocked_range<size_t>& r) { f(r); });

但是,std::for_each()只接受迭代器。

std::vector<int32_t> v(0, n);
std::for_each(std::execution::par,
v.begin(),
v.end(),
[&](int32_t& i) { f(i); });

如何解决这个问题?

大多数标准算法都在迭代器上运行,这就是它们的工作方式,因此它们可以与多个容器一起使用。

但是,std::vector使用随机访问迭代器,因此您可以将索引应用于begin迭代器,例如:

template<typename T, typename Callable>
void my_parallel_for(std::vector<T> &v, size_t startIdx, size_t endIdx, Callable c)
{
std::for_each(std::execution::par,
v.begin()+startIdx,
v.begin()+endIdx,
c);
}
std::vector<int32_t> v;
...
my_parallel_for(v, 0, n, [&](int32_t& i) { f(i); });

我终于找到了解决方案。

class Iterator
: public std::iterator<std::random_access_iterator_tag, int64_t, int64_t>
{
public:
Iterator() = default;
Iterator(int64_t index) : index_(index) {}
const int64_t& operator*() const { return index_; }
const void operator++() { ++index_; }
bool operator!=(const Iterator& lhs) const { return index_ != lhs.index_; }
const int64_t operator+(const Iterator& lhs) const { return index_ + lhs.index_; }
int64_t operator-(const Iterator& lhs) const { return index_ - lhs.index_; }
private:
int64_t index_;
};
std::for_each(std::execution::par,
Iterator(0),
Iterator(n),
[&](int64_t idx) { f(idx); });

您可以使用tbb::counting_iterator(https://www.threadingbuildingblocks.org/docs/help/reference/iterators/counting_iterator.html(

auto begin = tbb::counting_iterator<int>(0);
std::for_each(std::execution::par,
begin,
begin + n,
[&](int32_t& i) { f(i); });

Boost也有它:https://www.boost.org/doc/libs/1_71_0/libs/iterator/doc/counting_iterator.html