インテル コンパイラー 11.1では、並列処理を容易に実行するためのC/C++キーワードが新たに追加されている。これらはプログラム中で並列に実行できる処理をコンパイラに指示したり、それらの結果を集計するために利用できるものだ。
追加されたキーワードは表2の4つとなる。まず「__par」は並列実行できるforループを指定するもので、OpenMPの「omp parallel for」演算子とほぼ同様の働きをするものだ。
| キーワード | 同等のOpenMPディテクティブ |
|---|---|
| __par | #pragma omp parallel for |
| __taskcomplete | #pragma omp single |
| __task | #pragma omp task |
| __critical | #pragma omp critical |
また、「__taskcomplete」および「__task」はこのキーワードを付けた処理を別スレッドで実行するもので、OpenMPの「omp task」と似た働きをする。__taskcompleteと__taskはリスト6のように、必ずセットで利用される。
リスト6 「__taskcomplete」および「__task」キーワードによる処理の並列化
__taskcomplete
{
__task f_sum1(500, a, b, c);
__task f_sum2(500, a+500, b+500, c+500, d);
// 上記の関数「f_sum1」と「f_sum2」は、複数のスレッドで同時に実行され、
// 両方の関数の実行が完了したら__taskcomplete{}に続く処理が実行される
}
最後の__criticalはクリティカルセクション(複数のスレッドが同じ処理を実行する際、複数のスレッド間で同時に行ってはいけない処理)を指定するキーワードである。これにより、従来はMutexなどを利用して実装する必要があった処理を簡潔に記述できるようになる(リスト7)。この例では、「__par」キーワードを使ってforループ内を並列に実行するよう指定しており、複数のスレッドで同時に「num_founds」変数の値を更新しないよう、クリティカルセクションを利用している。
リスト7 クリティカルセクションの利用例
void count_keyword(char* buffer, char* keyword, int* num_founds) {
if( strcmp(word, keyword) == 0) {
__critical *num_founds++;
}
}
:
:
int i;
int num_founds;
char** buffer;
char* keyword;
:
:
num_founds = 0;
__par for( i = 0; i 128; i++ ) {
count_keyword(buffer[i], keyword,num_founds);
}
以上で述べたように、インテル コンパイラーではC++0xやOpenMP 3.0といった、最新の言語規格をいち早く利用できる。これらを利用することで、いままで面倒な記述が必要だったコードを簡潔にしたり、またコードの視認性を高めることが可能だ。これによって予想外の動作やバグを見つけやすく、また問題の対処もしやすくなると思われる。これらの機能はインテル コンパイラーの体験版でも利用できるので、ぜひ実際に試してみてほしい。