【发布时间】: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的建议,但发现这会导致性能下降。我怀疑它的实现并不能避免错误共享,因此会遇到与我的简单方法相同的问题。
标签: c++ multithreading algorithm vector