use*_*445 5 c++ parallel-processing c++17
我需要更新一个 100M 元素的数组,并且希望并行执行。 std::for_each(std::execution::par, ...)看起来很棒,除了更新需要根据我正在更新的索引访问其他数组的元素。我尝试并行化的最小串行工作示例可能如下所示:
for (size_t i = 0; i < 100'000'000; i++)
d[i] = combine(d[i], s[2*i], s[2*i+1]);
Run Code Online (Sandbox Code Playgroud)
我当然可以手动生成线程,但这比代码多得多std::for_each,因此找到一种使用标准库来执行此操作的优雅方法会很棒。到目前为止,我发现了一些不太优雅的使用方式for_each,例如:
通过对数组元素的地址使用指针算术来计算索引。
本着 boost 的精神实现我自己的伪造迭代器counting_range。
有一个更好的方法吗?
您应该能够迭代索引而不是项目。我认为 C++20std::ranges为您提供了一种简单的方法来做到这一点,或者您可以使用其中一种 Boostrange方法。我不知道为什么你会考虑本着Boost 的精神counting_range推出自己的产品,而你可以直接使用Boost :-)
话虽如此,我实际上选择了那种自己动手的方法,只是为了使代码独立,既不使用 C++20 也不使用 Boost:可以根据paxrange您的需要随意替换为其他方法之一:
#include <iostream>
#include <algorithm>
// Seriously, just use Boost :-)
class paxrange {
public:
class iterator {
friend class paxrange;
public:
long int operator *() const { return value; }
const iterator &operator ++() { ++value; return *this; }
iterator operator ++(int) { iterator copy(*this); ++value; return copy; }
bool operator ==(const iterator &other) const { return value == other.value; }
bool operator !=(const iterator &other) const { return value != other.value; }
protected:
iterator(long int start) : value (start) { }
private:
unsigned long value;
};
iterator begin() const { return beginVal; }
iterator end() const { return endVal; }
paxrange(long int begin, long int end) : beginVal(begin), endVal(end) {}
private:
iterator beginVal;
iterator endVal;
};
int main() {
// Create a source and destination collection.
std::vector<int> s;
s.push_back(42); s.push_back(77); s.push_back(144);
s.push_back(12); s.push_back(6);
std::vector<int> d(5);
// Shows how to use indexes with multiple collections sharing index.
auto process = [s, &d](const int idx) { d[idx] = s[idx] + idx; };
paxrange x(0, d.size());
std::for_each(x.begin(), x.end(), process); // add parallelism later.
// Debug output.
for (const auto &item: s) std::cout << "< " << item << '\n';
std::cout << "=====\n";
for (const auto &item: d) std::cout << "> " << item << '\n';
}
Run Code Online (Sandbox Code Playgroud)
该解决方案的“核心”是 中间的三行main(),您可以在其中设置一个回调函数,该函数采用索引而不是项目本身。
在该函数中,您可以使用该索引加上所需数量的集合来设置目标集合,这与您想要的非常相似。
就我而言,我只是希望输出向量成为输入向量,但根据输出将索引添加到每个元素:
< 42
< 77
< 144
< 12
< 6
=====
> 42
> 78
> 146
> 15
> 10
Run Code Online (Sandbox Code Playgroud)