我正在编写一些并行处理碰撞的代码,预期结果是每个线程都有一个加速,但我没有在数据处理上获得任何加速,因为我在 parallel_reduce 中有一个关键部分()
并且我相信它序列化了太多对对象的访问。这是代码的样子:
do {
totalVel = 0.;
#pragma omp parallel for
for (unsigned long i = 0; i < bodyContact.size(); i++) {
totalVel += bodyContact.at(i).bodyA()->parallel_reduce();
totalVel += bodyContact.at(i).bodyB()->parallel_reduce();
}
} while (totalVel >= 0.00001);
是否有任何方法可以通过使其并行化或访问的串行化过多来提高速度?
观察:
- bodyA() 和 bodyB() 是在 bodyContact 容器内多次重复自身的对象。
- 目前
parallel_reduce()
只做一次乘法(临界区),但会变得更复杂。
double parallel_reduce(){
#pragma omp critical
this->vel_ *= 0.99;
return vel_.length();
}
实际时间:
- 序列号,25.635
- 平行,123.559
最佳答案
使用 OpenMP 构造总是有成本的,因此避免在循环内使用并行,遵循它可以在每次启动新线程时启动的实现,而不是重新唤醒之前启动的线程。
事实上,如果 bodyContact.size() 很小,而 do {} while in step 很大,并且 parallel_reduce 非常快,那么仅用几个 OpenMP pragma 就很难实现可扩展性。
#pragma omp parallel shared(totalVel) shared(bodyContact)
{
do {
totalVel = 0.;
#pragma omp for reduce(+:totalVel)
for (unsigned long i = 0; i < bodyContact.size(); i++) {
totalVel += bodyContact.at(i).bodyA()->parallel_reduce();
totalVel += bodyContact.at(i).bodyB()->parallel_reduce();
}
} while (totalVel >= 0.00001);
}
关于c++ - 并行处理碰撞对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13371929/