gpt4 book ai didi

c++ - OpenMP:将原子部分包含到并行区域声明中

转载 作者:行者123 更新时间:2023-11-30 03:25:48 25 4
gpt4 key购买 nike

我有一个监控进度的并行区域。这意味着我使用变量 iteration 来计算循环的当前状态(百分比:0 - 100 直到循环完成)。

为此,我增加了一个atomic 操作。有没有办法让代码更短,也许是通过将 iteration++ 包含到 #pragma omp parallel for 子句中?

  int iteration = 0;
#pragma omp parallel for
for (int64_t ip = 0; ip < num_voxels; ip++)
{
// calc stuff
#pragma omp atomic
iteration++;
// output stuff
// if thread == 0:
// Progress(iteration / num_voxels * 100);
}

最佳答案

我认为不可能在循环体内以外的其他地方增加 iteration。例如,这是不允许的:

std::atomic<int> iteration{0};
#pragma omp parallel for
for (int64_t ip = 0; ip < num_voxels; ip++, iteration++) { ...

因为 OpenMP 需要所谓的规范循环形式,其中增量表达式可能不会更新多个变量(请参阅 OpenMP 4.5 规范的第 2.6 节)。


此外,我强烈建议不要在每个循环中递增 iteration,因为这会非常低效(原子内存操作 = 内存栅栏和缓存争用)。

我更喜欢,例如:

int64_t iteration = 0;
int64_t local_iteration = 0;
#pragma omp parallel for firstprivate(local_iteration)
for (int64_t ip = 0; ip < num_voxels; ip++) {
{
... // calc stuff
if (++local_iteration % 1024 == 0) { // modulo using bitwise AND
#pragma omp atomic
iteration += 1024;
}
// output stuff
// if thread == 0:
// Progress(iteration / num_voxels * 100);
}

并且,仅当进度百分比发生变化时才输出。这可能也很棘手,因为您需要以原子方式读取 iteration 并且您可能不希望在每次迭代中都这样做。一个可能的解决方案,它还节省了很多关于“昂贵的”整数除法的周期:

int64_t iteration = 0;
int64_t local_iteration = 0;
int64_t last_progress = 0;
#pragma omp parallel for firstprivate(local_iteration)
for (int64_t ip = 0; ip < num_voxels; ip++) {
{
... // calc stuff
if (++local_iteration % 1024 == 0) { // modulo using bitwise AND
#pragma omp atomic
iteration += 1024;

// output stuff:
if (omp_get_thread_num() == 0) {
int64_t progress;
#pragma omp atomic read
progress = iteration;
progress = progress / num_voxels * 100;
if (progress != last_prgoress) {
Progress(progress);
last_progress = progress;
}
}
}
}

关于c++ - OpenMP:将原子部分包含到并行区域声明中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48805373/

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