我有这个方法:
void A::overlapOut(int pos)
{
for(unsigned int j = 0; j < size; ++j)
{
out[pos+j] += local_arr[j] / scalingFactor;
}
}
我想使用类似 std::transform
的 STL 算法对其进行重构,主要是为了代码的一致性。
我还有大约五种其他方法,它们是主题的变体,我已经能够使用 std::transform
进行重构。或 std::copy
,像这样:
void A::nonOverlapOut(int pos)
{
auto normalize = [&] (double x) { return x / otherScalingFactor; };
std::transform(local_arr, local_arr + size, out + pos, normalize);
}
然而,这里的主要区别在于 +=
.我的所有其他功能都不重叠,并且不使用 data[i]
中的先前值所以可以进行并行调用,但是这个需要做 data[i] += stuff
, 而不是 data[i] = stuff
, 和 data[i]
可能会被其他也会做 +=
的线程访问.
那么,执行此操作的最佳 C++11-ic 方法是什么?我考虑过使用 std::atomic<double>
而不是 double
对于我的数组,但它会减慢我不需要原子访问的地方的计算速度吗?
最佳答案
std::transform
可以采用两个输入范围,输出迭代器可以与输入相同。
#include <iostream>
#include <algorithm>
int main() {
double local_arr[] = {9.0, 8.0, 5.0, 4.0, 5.0};
double out[] = {12.0, 24.0, 36.0, 48.0, 60.0, 72.0, 84.0};
auto scalingFactor = 7.0;
size_t size = 5;
size_t pos = 1;
std::transform(local_arr, local_arr + size, out + pos, out + pos,
[=](double a, double b) { return a / scalingFactor + b; });
for (auto v : out) {
std::cout << v << std::endl;
}
}
请注意,这会执行 data[i] = data[i] + stuff
而不是 data[i] += stuff
.所以制作data[i]
std::atomic<double>
的数组使用此代码不会产生单个原子指令。
但在您的情况下,不同的线程写入数组的不相交部分,因此没有冲突(§1.10/4),因此没有数据竞争(§1.10/21),因此不需要原子或线程安全锁。
关于c++ - 在允许并行性的情况下用 STL 算法替换 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17852292/