0

我遇到了一个非常奇怪的 OpenMP 问题,我无法弄清楚。这就是它的样子。

我有(比方说)四个功能

function0(Data *data) { ..body.. }
function1(Data *data) { ..body.. }
function2(Data *data) { ..body.. }
function3(Data *data) { ..body.. }

这些功能可能会或可能不会修改所指向的内容data

以下是它们的顺序调用方式

// Version 1

void test(Data *data)
{
    function0(data);
    function1(data);
    function2(data);
    function3(data);
}

我可以以任何我想要的方式重新安排电话,它仍然可以完美运行。所以我假设他们以某种方式(?)独立。

现在并行化时

// Version 2

void test(Data *data)
{
  int th_id;
#pragma omp parallel private(th_id) default(shared)
  {
    th_id = omp_get_thread_num();
    if(th_id==0) {
      function0(data);
    }

    if(th_id==1) {
      function1(data);
      }

    if(th_id==2){
      function2(data);
    }

    if(th_id==3){
      function3(data);
    }
  }
}

它不起作用(第 2 版)。

但是,如果我在每次调用后同步线程,它就可以工作

// Version 3

void test(Data *data)
{
  int th_id;
#pragma omp parallel private(th_id) default(shared)
  {
    th_id = omp_get_thread_num();
    if(th_id==0) {
      function0(data);
    }
#pragma omp barrier
    if(th_id==1) {
      function1(data);
      }
#pragma omp barrier
    if(th_id==2){
      function2(data);
    }
#pragma omp barrier
    if(th_id==3){
      function3(data);
    }
  }
}

我认为关于所指出的内容存在一些数据竞赛问题data

但是,当我重新安排呼叫时,为什么它会起作用(在顺序版本 1 中)?

4

1 回答 1

2

假设你有两个这样的功能

function0(int *data)
{
    *data = *data + 1;
}

function1(int *data)
{
    *data = *data + 2;
}

显然,您可以按任意顺序依次运行这两个操作,最后值将增加 3。但是,如果您并行运行这两个函数,则会出现数据竞争,并且完全有可能其中一个添加将丢失,因此您可以获得任何增加 1,2 或 3 的初始值。

仅仅因为函数看起来是顺序可交换的,并不意味着它们可以安全地并行运行。

于 2013-03-07T16:50:30.193 回答