c - OpenMP 任务和 while 循环

标签 c task openmp

我很难理解以下代码中发生的事情:

/*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/

相关文章:

c# - 在延续链中传播异常的正确方法是什么?

c++ - OpenMP:共享同一算法的单线程和多线程实现

multithreading - OpenMP while 循环

c - 如何在unix中获取完全限定域名

c - avr内联汇编错误: impossible constraint

使用 ns_initparse() 函数编译程序 C linux

sql - 在 SSIS 中使用 OLE DB 命令的查询中的多个参数

c# - 使用异步等待或任务?

c - 如何访问整数形式的字节

c - OpenMP 错误 : 'X' is predetermined 'shared' for 'private'