C++ C++;17:如何在并行STL中获取工作项的索引
在并行算法中有没有办法知道工作项的ID/索引 例如,在生成物联网时,这将非常有用:C++ C++;17:如何在并行STL中获取工作项的索引,c++,stl,c++17,C++,Stl,C++17,在并行算法中有没有办法知道工作项的ID/索引 例如,在生成物联网时,这将非常有用: std::vector<int> vec(max_size); std::for_each(std::execution::par, vec.begin(), vec.end(), [](int& elem) { elem = work_item_index; }); std::向量向量向量(最大大小); std::for_each(std::execution::par,v
std::vector<int> vec(max_size);
std::for_each(std::execution::par, vec.begin(), vec.end(),
[](int& elem) {
elem = work_item_index;
});
std::向量向量向量(最大大小);
std::for_each(std::execution::par,vec.begin(),vec.end(),
[](国际和电子){
elem=工作项目索引;
});
但是如何有效地计算
工作项目索引
值?编辑:这种方法不能保证有效,因为在并行执行中不能依赖元素标识(即地址)
正确的解决方案是将迭代器范围与索引范围联系起来,如Caleth的答案所示
您可以使用指针算法:
int* beg = vec.data();
std::for_each(std::execution::par, vec.begin(), vec.end(),
[beg](int& elem) {
elem = &elem - beg;
});
显然,这只适用于连续存储元素的容器。
您在包含索引的范围内操作
std::vector<int> vec(max_size);
auto indexed_vec = ranges::view::zip(vec, ranges::view::indices(vec));
std::for_each(std::execution::par, indexed_vec.begin(), indexed_vec.end(),
[](std::tuple<int&, int> elem) {
std::get<0>(elem) = std::get<1>(elem);
});
std::向量向量向量(最大大小);
自动索引_vec=ranges::view::zip(vec,ranges::view::index(vec));
std::for_each(std::execution::par,indexed_vec.begin(),indexed_vec.end(),
[](标准::元组元素){
std::get(elem)=std::get(elem);
});
实际上它不是标准化的。它依赖于用于算法并行化的并行引擎。
例如,omp\u get\u thread\u num()
用于OpenMP
但是,如果您只想获得向量当前处理元素的索引,可以使用计数迭代器。
一旦它也是非标准功能,您就可以从库中使用它:
std::向量向量向量(最大大小);
auto first=vec.begin();
std::for_each(std::execution::par,counting_迭代器(0),counting_迭代器(max_size),
[第一](内部和工作项目索引){
第一个[工作项索引]=工作项索引;
});
@RichardCritten是的,没有明确的API来获取工作项索引,所以我只是想知道生成它的最有效方法是什么!因此,这可能是std::vector
的并行物联网的手动版本,但根据规范:“这意味着用户提供的函数对象不应依赖于此类输入序列参数的对象标识”(因为这些元素可能被复制)@it。你说得对。我认为我的答案不正确。你需要像另一个答案所建议的那样使用iota压缩。因此,它依赖于实现,在MSVC上似乎可以正常工作,但这不是一种通用和适当的方法另一个更正:)因为每个元素都不能复制元素,所以“技巧”是安全的,但对于其他算法(如transform)来说是不安全的:“与其他算法不同,for_每个算法都不允许复制序列中的元素,即使这些元素很容易复制。“-有没有不需要范围的解决方案?@fen嗯,还有其他的,或者你可以自己编写机器我似乎找不到视图::索引
,这是正确的视图吗?@user975989 oops,视图::索引
也不起作用,索引
需要一个积分
,尽管我希望它需要一次运行。”通用电气。
std::vector<int> vec(max_size);
auto first = vec.begin();
std::for_each(std::execution::par, counting_iterator<int>(0), counting_iterator<int>(max_size),
[first](int& work_item_index) {
first[work_item_index] = work_item_index;
});