我很难理解以下代码中发生的事情:
/*runs with 4 threads*/
int count_good(item_t* item){
int n=0;
int pn[num_thr];
#pragma omp parallel
{
pn[omp_get_thread_num()]=0;
#pragma omp single nowait
{
while(item){
#pragma omp task firstprivate(item)
{
if(is_good(item))pn[omp_get_thread_num( )]++;
}
item = item ->next;
}
}
#pragma omp atomic
n+=pn[omp_get_thread_num()];
}
return n;
}
首先打开一个并行区域,一个线程进入 while 循环。每次循环再次开始时,这个线程都会挂起一个任务。线程将任务推送到任务队列。其他线程可以从队列中取出任务并执行它。 它是否正确?还是我理解有误?
最佳答案
您关于任务如何工作以及这段代码试图做什么的模型是正确的。一个线程正在创建任务(并且,当它完成后也执行它们),而其他线程只是在执行它们。
代码通过计算每个线程看到的“好”项的数量来执行总和减少。 (在 OpenMP 5.0 中,它可以使用任务缩减)。
尽管我之前说过(对此我深表歉意),这段代码是正确的,因为在单个语句的末尾有一个隐式屏障。因此,除了执行单个语句的线程外,所有线程都在那里等待,然后拾取和执行任务。一旦执行单个语句的线程耗尽了列表(并生成了所有任务),它也会到达屏障并开始执行任务。一旦所有任务都已执行,屏障就可以完成。此时线程将继续(原子地)将它们的贡献添加到全局总和中。
我忘记的是与单个语句相关的隐式屏障(这有点令人困惑,因为看起来类似的主语句没有!)。不过,既然有一个,这段代码就可以了。 (除了性能问题外,每线程累加器将受到大量错误共享的影响。为避免每个累加器都应填充到缓存行的大小 [x86 上为 64 字节])。
关于c - OpenMP 任务和 while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51876958/