有条件地并行填充向量
Posted
技术标签:
【中文标题】有条件地并行填充向量【英文标题】:conditionally filling a vector in parallel 【发布时间】:2018-11-22 12:37:11 【问题描述】:我想写下面代码的多线程版本
template<typename Out, typename In, typename Cond, typename Func>
std::vector<Out> collect(std::vector<In> const&values,
Cond const&cond, Func const&func)
std::vector<Out> result;
for(auto const&val : values)
if(cond(val))
result.emplace_back(func(val));
return result;
选择元素的顺序无关紧要。
一种简单的方法是
template<typename Out, typename In, typename Cond, typename Func>
std::vector<Out> collect(std::vector<In> const&values,
Cond const&cond, Func const&func)
std::vector<Out> result(values.size());
std::atomic<size_t> index = 0;
// some multithreaded for loop implementation
parallel_for(size_t(0),values.size(),[&](size_t i)
if(cond(values[i]))
result[index++] = func(values[i]);
);
result.resize(index);
return result;
(当然,初始化result
是串行的,但我们在这里忽略它)。这似乎有效,但可能不是无锁的。有没有更好的办法?特别是,我能否避免分配太多数据(如果只选择了少数输入数据)?
问题与std::copy_if
非常相似(应该是std::transform_if
它存在)——并行版本std::copy_if(std::par,...)
是如何实现的(它是C++17,但我仅限于C+ +11)?
【问题讨论】:
我不会让所有线程写入同一个向量,而是每个线程都写入自己的并最终合并它们,这样你只需要同步一次而不是“一直” 如果你已经使用了tbb
(从你的parallel_for
暗示),为什么还要使用std::vector
来并发push_back
? tbb::concurrent_vector
专为并发访问而设计。
似乎高度依赖于您的确切细节,但复制到单独的向量和合并听起来不错。
@PasserBy +1,另外使用单独的向量,甚至写在同一向量的单独跨度中,真的会increase the performance。
@liliscent 我尝试了使用tbb::concurrent_vector
的建议,但发现这会导致性能下降。我怀疑它的实现并不能避免错误共享,因此会遇到与我的简单方法相同的问题。
【参考方案1】:
一个不错的方法是使用最后合并的线程局部向量。如果不是因为它使用 OMP,这个答案(特别是最后一个代码示例)将是一个很好的副本:
https://***.com/a/18671256/9528746
编辑:更改为更好的答案。
【讨论】:
主要区别不是OMP的东西,而是我只收集选定的项目。以上是关于有条件地并行填充向量的主要内容,如果未能解决你的问题,请参考以下文章
是否有一个足够智能的并行制造系统可以智能地响应低内存/交换条件?