2016-09-26 16 views
0

この問題は、本質的に、大きな(> 20GB)データファイルで、ある程度の関数void lineProcess(string, string&, int[])を計算することを含んでいます。計算は非常に重く、配列パラメータの長さとランダム性にもかなり依存します。いくつかのテストランで平均した時間。最初のパラメータはファイルの1行、2番目は文字列のアドレスで結果を出力することができます。出力の合計サイズは3MBです。入力と出力のk番目のラインが対応する必要はありません。ファイルioとは別に、並列化には完璧に聞こえるので、ここではコードを示します。C++ OpenMPとファイルioによる並列化。パフォーマンスの問題

void foo(const int param[]) { 
    // process some stuff ... 
    // create input stream fin, output stream fout from <iostream> 
    string result; 
    for (string line; getline(fin, line);) { 
#pragma omp parallel task firstPrivate(result) 
     lineProcess(line, result, param); 
     fout << result << endl; 
    } 
#pragma omp task wait 
    fin.close(); 
    fout.close(); 
} 

私はラップトップ上でそれを数回走ってきました(i7のクアッドコア、ハイパースレッディングと8つのプロセスをサポートする必要があります)と大幅にスピードアップを見ているように見えません。シリアルラインプロセス(すなわち、上記のマイナスプラガマディレクティブ)の平均値は、〜2800秒/行で、パラレル〜2000秒/ラインです。私は〜600秒/ラインの数字を目指していました。私は、問題の一部は、タスクとtaskwaitを使用してopenMPの実装かもしれないと思うが、私はファイルの行数がわからないので、簡単な方法で#pragma omp forを見ることができなかった。
理想的には、私は、1つのバッファがほぼ空/フルになってから、スレッドが読み書きによってディスクを補充/空にするまでスワップするまで、 OpenMPでこれが可能であるかどうか、または読み書きの間でスワップするだけの1つのスレッドでこの単純なバージョンを実行できるかどうかはわかりません。 これが期待どおりに速くない理由やパフォーマンスを向上させる方法についてのアドバイスをいただければ幸いです。明らかに、多くのデータを読み書きするという基本的な限界がありますが、ライン処理にはかなりの時間がかかります。

私はこの質問を非常によく似た方法で見つけましたopenmp - while loop for text file reading and using a pipeline最初の答えは自分のコードとよく似ていますが、2番目のバッファはバッファを使用しているようですが、完全にそれを適応させる方法や価値があるかどうかはわかりません。

答えて

0

forループの前に並列領域を開く必要があります。これは、複数のスレッドが実行されている1つの並列領域を生成します。タスクを作成する時点で、タスクを実行する準備が整ったスレッドが実行されています。

#pragma omp parallel 
{ 
#pragma omp single 
{ 
    for(...) 
    { 
    #pragma omp task 
    lineProcess(...) 
    fout ... 
    } 
} 
#pragma omp taskwait 
} 

ここ並列領域が最初に開かれると、唯一のタスクを生成している一つのスレッドによってprocresedれるためfollwoing、それは今度は複数のスレッドによって加工ARREことが記載されています。すべての行を処理した後(taskwait)、通常のコードの実行を続行できます。

また、lineProcess関数だけがタスクであることに注意してください。そのタスクが生成された後(まだ作業されていないか完了していない)、生成スレッドはfout行に移動してそれを処理します。あなたはこのようにして対処することができます:

#pragma omp task 
{ 
lineProcess(...) 
fout ... 
fout.flush(); 
} 
関連する問題