For 循环中的 OpenMP 并行部分 (C++) - 开销
OpenMP Parallel Sections Within For Loop (C++) - Overhead
我一直在研究量子模拟。每个时间步计算一个势函数,迭代求解器的一个步骤,然后进行一系列测量。这三个过程很容易并行化,而且我已经确保它们不会相互干扰。此外,还有一些相当简单的事情,但不应该并行完成。设置概要如下所示。
omp_set_num_threads(3);
#pragma omp parallel
{
while (notDone) {
#pragma omp sections
{
#pragma omp section
{
createPotential();
}
#pragma omp section
{
iterateWaveFunction();
}
#pragma omp section
{
takeMeasurements();
}
}
#pragma omp single
{
doSimpleThings();
}
}
}
代码工作得很好!我看到速度提高了,主要与测量 运行ning 以及 TDSE 求解器相关(大约 30% 的速度提高)。但是,该程序从使用大约 10% CPU(大约一个线程)到 35%(大约三个线程)。如果潜在函数、TDSE 迭代器和测量花费同样长的时间,这将是有意义的,但事实并非如此。根据速度的提高,我预计使用量会增加 15% CPU。
我感觉这与在 while 循环中 运行这三个线程的开销有关。正在替换
#pragma omp sections
与
#pragma omp parallel sections
(并省略循环之前的两行)没有任何改变。 运行 这个设置有更有效的方法吗?我不确定线程是否不断被重新创建,或者线程是否在等待其他线程完成时占用了整个核心。如果我将线程数从 3 增加到任何其他数字,程序会使用它想要的资源(可能是所有 CPU)并且不会获得性能提升。
我尝试了很多选项,包括使用任务而不是部分(结果相同)、切换编译器等。根据 Qubit 的建议,我也尝试使用 std::async。这就是解决方案! CPU 使用率从大约 50% 下降到 30%(这是在与原始 post 不同的计算机上,所以数字不同——性能提升 1.6 倍 [=19] =] 基本用法)。这更接近我对这台电脑的预期。
作为参考,这里是新的代码大纲:
void SimulationManager::runParallel(){
auto rV = &SimulationManager::createPotential();
auto rS = &SimulationManager::iterateWaveFunction();
auto rM = &SimulationManager::takeMeasurements();
std::future<int> f1, f2, f3;
while(notDone){
f1 = std::async(rV, this);
f2 = std::async(rS, this);
f3 = std::async(rM, this);
f1.get(); f2.get(); f3.get();
doSimpleThings();
}
}
使用 std::async 调用三个原始函数,然后我使用 future 变量 f1、f2 和 f3 将所有内容收集回单个线程并避免访问问题。
我一直在研究量子模拟。每个时间步计算一个势函数,迭代求解器的一个步骤,然后进行一系列测量。这三个过程很容易并行化,而且我已经确保它们不会相互干扰。此外,还有一些相当简单的事情,但不应该并行完成。设置概要如下所示。
omp_set_num_threads(3);
#pragma omp parallel
{
while (notDone) {
#pragma omp sections
{
#pragma omp section
{
createPotential();
}
#pragma omp section
{
iterateWaveFunction();
}
#pragma omp section
{
takeMeasurements();
}
}
#pragma omp single
{
doSimpleThings();
}
}
}
代码工作得很好!我看到速度提高了,主要与测量 运行ning 以及 TDSE 求解器相关(大约 30% 的速度提高)。但是,该程序从使用大约 10% CPU(大约一个线程)到 35%(大约三个线程)。如果潜在函数、TDSE 迭代器和测量花费同样长的时间,这将是有意义的,但事实并非如此。根据速度的提高,我预计使用量会增加 15% CPU。
我感觉这与在 while 循环中 运行这三个线程的开销有关。正在替换
#pragma omp sections
与
#pragma omp parallel sections
(并省略循环之前的两行)没有任何改变。 运行 这个设置有更有效的方法吗?我不确定线程是否不断被重新创建,或者线程是否在等待其他线程完成时占用了整个核心。如果我将线程数从 3 增加到任何其他数字,程序会使用它想要的资源(可能是所有 CPU)并且不会获得性能提升。
我尝试了很多选项,包括使用任务而不是部分(结果相同)、切换编译器等。根据 Qubit 的建议,我也尝试使用 std::async。这就是解决方案! CPU 使用率从大约 50% 下降到 30%(这是在与原始 post 不同的计算机上,所以数字不同——性能提升 1.6 倍 [=19] =] 基本用法)。这更接近我对这台电脑的预期。
作为参考,这里是新的代码大纲:
void SimulationManager::runParallel(){
auto rV = &SimulationManager::createPotential();
auto rS = &SimulationManager::iterateWaveFunction();
auto rM = &SimulationManager::takeMeasurements();
std::future<int> f1, f2, f3;
while(notDone){
f1 = std::async(rV, this);
f2 = std::async(rS, this);
f3 = std::async(rM, this);
f1.get(); f2.get(); f3.get();
doSimpleThings();
}
}
使用 std::async 调用三个原始函数,然后我使用 future 变量 f1、f2 和 f3 将所有内容收集回单个线程并避免访问问题。