我正在编写一些用于并行处理冲突的代码,预期的结果是为每个线程加速,但是我没有在数据处理上获得任何加速,因为我在{{1}内部有一个关键部分我相信它序列化了对对象的访问权限。这就是代码的外观:
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);
只进行一次乘法(关键部分),但会变得更复杂。parallel_reduce()
实际时间:
答案 0 :(得分:1)
使用OpenMP结构总是有成本的,所以避免在循环中使用并行,遵循每次新线程时可以启动的实现,而不是重新启动先前启动的线程。
实际上,如果bodyContact.size()很小,而且步骤数量为do {}且并行,则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);
}
答案 1 :(得分:0)
上述情况不仅可能更慢,而且很可能是错误的;所有线程都试图更新相同的totalVel。吨竞争条件,但也有争用,缓存失效等等。
假设parallel_reduce()
的东西没问题,你会喜欢更像
do {
totalVel = 0.;
#pragma omp parallel for default(none) shared(bodyContact) reduction(+: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);
将正确执行totalVel
上的reduction。