• Showing Page History #49437

Parallel Composerを利用したプログラムの並列化 続けて、Parallel Studioのインテル C++ コンパイラーが備える並列化キーワードを利用して、プログラムを並列化してみよう。今回はクイーンの数を求める「setQueen」関数を呼び出しているforループを並列実行することで、プログラムの並列化を行ってみる。

 まず、並列化したいforループにインテル C++ コンパイラーの独自拡張キーワード「__par」を追加する。__parキーワードは、このキーワードを付加した部分を並列に実行するように指定するものだ。また、変数「queens」は探索に利用するための作業用バッファであるので、スレッドごとに独立してメモリを割り当てておく。

変更前:{{{ void solve(int queens[]) {

for(int i=0; isize; i++) {
// try all positions in first row // create separate array for each recursion setQueen(queens, 0, i);
}

} }}}

変更後:{{{ void solve() {

int* queens;__par for(int i=0; isize; i++) {
// try all positions in first row // create separate array for each recursionqueens = new intsize; setQueen(queens 0, i);delete[] queens;
}

} }}}

 また、setQueens関数中ではグローバル変数「nrOfSolutions」の変更を行う個所があり、複数のスレッド間で同時にこの値を変更してしまうと問題が発生する。そこで、あるスレッドがこの変数に対する処理を行っている間は、ほかのスレッドから同じ処理を実行できないように「__critical」キーワードを追加する。

変更前:{{{

if(row==size-1) {
nrOfSolutions++;
}

}}}

変更後:{{{

if(row==size-1) {__critical nrOfSolutions++; }

}}}

 これらの変更を加えたのち、再度プログラムをコンパイルしてパフォーマンスを比較したところ、次のように大幅な高速化が確認できた(表3)。

表3 並列化前と並列化後のパフォーマンス比較
条件実行時間
並列化前1335ミリ秒
並列化後758ミリ秒

 なお、__parや__criticalキーワードを利用したプログラムをコンパイルする際は、コンパイルオプションでOpenMPを利用するように設定しておく必要がある(図9)。