2017-12-08 20 views
0

私は現在、大きなデータセットで動作し、最後に配列を生成するコードを持っています。これは、グローバルバッファに配列を追加する必要があり、これはすべてループ内で発生します。例えば。openmpにタスクを含むアルゴリズムを設計する

for(i=0;i<10000;i++) 
{ <1. do some processing, generate a 1M-sized array> 
    <2. update this array into global buffer> 
} 

タスク1は、GPU上で起こる、と私は第二の部分はCPU、すなわち1つのスレッドがタスク1のためにGPUを制御し、1バッファの準備ができたとき、他のすべてのスレッドがタスク2を行う場所に並列に発生します処理のために。基本的なケースでは、バッファの1つのコピー(GPU側で1つ、CPU側で1つ)でどのようにすればGPUコピーを受け取ることができますか?

+0

実際には、ステップ1をステップ2と並行して実行し、可能であればマルチスレッドのステップ2も実行する必要があります。ステップ1とステップ2をパラレル化するには、ステップ2で新しいバッファが生成されていることが分かり、ステップ1で古いバッファを上書きするタイミングがわかるように、同期が必要です。ステップ2は要素ごとに1Mサイズの配列要素を調べ、いくつかの条件を満たしている場合は、グローバルバッファ配列内の適切な場所を探して追加してから追加します。 – udyank

答えて

0

手順1でバッファが作成され、手順2でそのバッファが消費され、結果がグローバル配列に組み込まれるような、プロデューサとコンシューマのタスクセットがあります。

何か(+ single通常parallel内部)等:

const int buffer_size = 100000; 
type global[buffer_size]; 
type buffer[2][buffer_size]; 

for(int i=0;i<10000;i++) 
{ 
    type *buf[buffer_size] = buffer[i % 2]; 
    #pragma omp task depend(out: [buffer_size]buf) 
    { 
     <1. write to buf> 
    } 

    #pragma omp task depend(in: [buffer_size]buf) depend(inout: [buffer_size]global) 
    { 
     <2. update global using buf> 
    } 
} 

これはそれが反復i = 1人の意志のステップ1で、 "遅れ" の1回の繰り返しで、ステップ1とステップ2と重複することを可能にしますステップ2の反復i = 0に並行して実行されます。 反復の重複につき1つのバッファが必要となり、各同時操作は互いに独立して実行できます。

ここで、buf(in/out)のセマンティクスは、単純なプロデューサ - 消費者関係であるため、単純です。グローバルでは、現在の配列(in)を取得し、新しい値を割り当てます(out)。インプレースでバッファを更新するときには、inoutが必要です。これは、ステップ2のすべてのタスクがこの依存関係のために直列化されることを意味します。つまり、最大で2回の繰り返しが重複している可能性があります(2つ以上のバッファを使用している点はありません)。

これは現在のOpenMP(4.5)タスクの制限ですが、これを解決するa proposal for task reductionsが存在します。代わりに、グローバルをsharedと宣言することもできます。その場合は、アトミック操作を使用して変更する必要があります。

target句を使用して、GPUでタスク1を実行できます。オフロードされたデバイス(GPU)からのデータがCPUにコピーされていることを確認します。ステップ2のタスクの中で、並列のfor構文を使用してステップ2を並列化するか、タスクを再度実行することができます。

関連する問題