gpt4 book ai didi

c++ - openmp parallel for with non-PODs

转载 作者:行者123 更新时间:2023-11-28 08:19:47 25 4
gpt4 key购买 nike

我正在尝试加速一个程序,该程序的核心是一个看起来很普通的循环:

double sum=0.;
#pragma omp parallel for reduction(+:sum) // fails
for( size_t i=0; i<_S.size(); ++i ){
sum += _S[i].first* R(atoms,_S[i].second) ;
}

虽然循环本身很简单,但其中的对象不是 POD:这里的 _S 实际上是一个 std::vector< std::pair<double, std::vector<size_t> > > , 和 R(...)是重载 operator(...) const一些对象。它的两个参数都符合 const 的条件。 ,这样调用就没有任何副作用。

由于大约 90% 的运行时间都花在了这个调用上,因此将 OpenMP pragma 放入如上所示并享受两到三倍的加速似乎是一件简单的事情; 但当然---代码在单个线程下工作正常,但对于多个线程给出明显错误的结果:-)。

没有数据依赖,两者都是_SR(...)在线程之间共享似乎是安全的,但它仍然会产生废话。

我非常感谢任何关于如何找出问题所在的指示。

UPD2:

想通了。与所有错误一样,它是微不足道的。 R(...)正在调用 operator()这类东西:

class objR{
public:
objR(const size_t N){
_buffer.reserve(N);
};
double operator(...) const{
// do something, using the _buffer to store intermediaries
}

private:
std::vector<double> _buffer;
};

很明显,不同的线程使用 _buffer同时把它搞砸。到目前为止,我的解决方案是分配更多空间(内存不是问题,代码受 CPU 限制):

class objR{
public:
objR(const size_t N){
int nth=1;
#ifdef _OPENMP
nth=omp_get_max_threads();
#endif
_buffer.resize(N);
}

double operator(...) const{
int thread_id=0;
#ifdef _OPENMP
thread_id = omp_get_thread_num();
#endif
// do something, using the _buffer[thread_id] to store intermediaries
}

private:
std::vector< std::vector<double> > _buffer;
};

这似乎工作正常。尽管如此,由于这是我第一次涉足多线程事物,如果有知识渊博的人可以评论是否有更好的方法,我将不胜感激。

最佳答案

访问 _S[i].first_S[i].second 是绝对安全的(不能保证任何关于 atom).这意味着您对 R 的函数调用一定是导致问题的原因。您需要了解什么是 R 并发布它的作用。

另一方面,以下划线开头和大写字符开头的名称保留用于实现,您可以通过使用它们来调用未定义的行为。

关于c++ - openmp parallel for with non-PODs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6285715/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com