我很难理解下面的代码会发生什么:
/*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循环。每当循环再次开始时,该线程都会挂起一项任务。线程将任务推送到任务队列。其他线程可以从队列中获取任务并执行它。 它是否正确?还是我理解错误?
答案 0 :(得分:2)
您在模型上正确地说明了任务如何工作以及此代码正在尝试执行的操作。单个线程正在创建任务(然后,完成任务后还会执行任务),而其他线程正在执行任务。
该代码通过计算每个线程看到的“好”项目的数量来执行总和减少。 (在OpenMP 5.0中,它可以使用任务减少功能。)
尽管我之前说过(对不起),但是该代码是正确的,因为在单个语句的末尾存在隐式障碍。因此,除了执行单个语句的线程之外,所有线程都在那里等待,然后拾取并执行任务。一旦执行单个语句的线程用尽了列表(并生成了所有任务),它也到达障碍并开始执行任务。一旦完成所有任务,屏障即可完成。这时线程将继续移动(从原子上)将其贡献添加到全局总和中。
我忘记的是与单个语句相关的隐式障碍(这有点令人困惑,因为看起来类似的主语句没有一个!)。由于有一个,因此此代码很好。 (除了性能问题之外,每个线程的累加器还将遭受很多错误共享。为避免每个累加器都应填充到高速缓存行的大小[x86上为64Bytes]。)