0

私は理解できない非常に奇妙なOpenMPの問題に遭遇しています。こんな感じです。

私は(言いましょう)4つの機能を持っています

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

このような2つの機能があるとします

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

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

明らかに、これら2つの操作をいずれかの順序で順番に実行でき、最後に値が3ずつ増加します。ただし、2つの関数を並行して実行すると、データ競合が発生し、追加の1つが実行される可能性があります。失われるため、初期値を1、2、または3ずつ増やすことができます。

関数が順番に可換であるように見えるからといって、それらが安全に並列で実行できることを意味するわけではありません。

于 2013-03-07T16:50:30.193 に答える