OpenMP 和不平衡嵌套循环

OpenMP and unbalanced nested loops

本文关键字:嵌套循环 不平衡 OpenMP      更新时间:2023-10-16

我正在尝试使用 OpenMP 编译指示并行化用 C++ 编写的模拟器。 我对此有基本的了解,但没有经验。

下面的代码显示了并行化的主要方法:

void run(long long end) {
while (now + dt <= end) {
now += dt;
for (unsigned int i=0; i < populations.size(); i++) {
populations[i]->update(now);
}
}
}

其中populations是类Population的实例的std::vector。每个人口更新自己的元素,如下所示:

void Population::update(long long ts) {
for (unsigned int j = 0; j < this->size(); j++) {
if (check(j,ts)) {
doit(ts, j);
}
}
}

由于每个种群的大小不同,Population::update()中的循环需要不同的时间,从而导致次优加速。通过在run()方法中添加#pragma omp parallel for schedule(static)。我在 2 个线程下获得了 4 倍的加速,但是它下降了 8 个线程。

我知道schedule(dynamic)子句,允许平衡线程之间的计算。但是,当我尝试动态调度线程时,我没有观察到任何改进。

我走对了方向吗?你认为玩禅盘尺寸会有所帮助吗?任何建议不胜感激!

所以有两件事需要区分: 线程数和调度策略的影响。

对于线程数,线程数多于内核数通常会降低性能,因为上下文切换。所以这取决于您计算机上的内核数量

为静态和动态生成的代码(至少据我所知)之间的区别在于,使用静态调度时,循环迭代平均除以线程数,而使用动态调度时,分布是在运行时计算的(每次迭代结束后,使用 __builtin_GOMP_loop_dynamic_next 查询 omp 运行时)。 切换到动态时观察到的减速的原因可能是循环不包含足够的迭代/计算,因此动态计算迭代分布的开销无法被性能增益所覆盖。

(我假设每个人口实例不与其他实例共享数据)

只是抛出想法,希望这有帮助=)