ZipRange
/
std::views::zip
实现,并在tbb的parallel_for_each
#include <ranges>
#include <vector>
#include <iostream>
#include <algorithm>
#include <tbb/parallel_for_each.h>
int main()
{
const std::vector<int> ints{1,2,3};
const std::vector<double> doubles{0.1, 0.2, 0.3};
const auto multiply = [](auto&& intDoubleProduct)
{
auto&& [i, d, product] = intDoubleProduct;
product = i * d;
};
{
std::vector<double> product = {0, 0, 0};
std::ranges::for_each(std::views::zip(ints, doubles, product), multiply);
std::cout << "std::ranges::for_each result: (";
for(auto value : product)
std::cout << value << ", ";
std::cout << '\n';
}
{
std::vector<double> product = {0, 0, 0};
tbb::parallel_for_each(std::views::zip(ints, doubles, product), multiply);
std::cout << "tbb::parallel_for_each result: (";
for(auto value : product)
std::cout << value << ", ";
std::cout << '\n';
}
}
时跑进墙壁。
在我们自己的ziprange中,它完全能够修改Ziprange返回的元素之一,但是当我用std :: views :: zip替换它时,函子似乎会获得副本,而不是当我作为我的修改参考会期望的,导致Parallel_For_each必须实现并使“结果”容器未修改。与我们(非常有用的)内部zipiterator/ziprange和std :: ranges :: for_each一起做的事情,但tbb :: parallel_for_each使元素不变,如该计划所证明:
std::views::zip
我可以如何与tbb::parallel_for_each
一起读取?
我发现的唯一相关参考是看来TBB代码中对错误的接纳,但我认为长期以来已经解决了(我再也找不到引用的代码,所以也许在某些重构中丢失了这种情况他们的结局?):
我不确定这一点,但是tbb的parallel_for_each不会“浏览” std :: views :: zip生产的代理 - 它最终传递了元组的副本,因此修改该副本不会更新您的副本原始容器。一个事实证明的解决方法是通过通过std :: views :: all对zip视图进行管道视图来“实现”基础引用。例如,将您的呼叫更改为:
tbb::parallel_for_each(
std::views::zip(ints, doubles, product) | std::views::all,
multiply
);
由于TBB的算法如何推论和传递其元素(需要向前迭代的语义),而STD :: views :: Zip返回不太满足该要求的代理对象,因此这是由于TBB的算法如何推导和传递其元素(要求向前迭代的元素)引起的。使用STD :: View ::所有“将”代理“解开”到适当的引用中。