マツド・サイエンス研究所

デュアルコア対応プログラミング OpenMP 編

先日、「デュアルコア対応プログラミング」のコンテンツを書き込んだ時は、Cなどのコンパイル言語でのデュアルコア対応プログラミングは未完成であった。

今回は、ちゃんとコンパイル言語でデュアルコアに対応し、高速で計算するプログラムを作ることに成功したので、報告する。

課題は、先日と同じく円周率を求める計算だが、デュアルコアを有効に使って計算するプログラムは下のようになった。

#include 

main()
{
int i;
int n = 1000000000;
double s = 0.0;
system("date");
#pragma omp parallel for reduction(+:s)
for (i = 0;i < n;i++)
s += (4.0 / (4 * i + 1) - 4.0 / (4 * i + 3));
printf("%lf\n",s);
system("date");
}

「えっ、これだけ!?」

そう思うだろう。

ごく普通の C プログラムだ。ただ、「#」で始まる一行のみが、普通の C ではない。

たった一行でデュアルコアどころかクワッドコア、オクタコアの様なマルチコアに対応したプログラムになる。

意外なほど、簡単にマルチコア対応のプログラミングは可能なのだ。その秘密は OpenMP だ。

先日の「デュアルコア対応プログラミング」をアップした後、私なりに高速の計算をデュアルコアで行う方法を探して居た。

前回、C++ でのスレッド(pthread)を使って、プログラミングしたところ、シングルコアでの計算よりも時間がかかった。調べてみたところ、「マルチコアCPUのための並列プログラミング」(秀和システム ISBN:4-7980-1462-1)と言う本に pthread を使った「デュアルコア対応プログラミング」が詳しく載っている。ところが、この本を書店でパラパラとめくってみたところ、これは大変な手間だと言うことが判った。とりあえず、その場は買わずに保留とした。

その後、ネット上で調べてみると、OpenMP と言う機能を使うと、比較的簡単にマルチコアでの並列計算ができると言うことが判った。しかし、OpenMP と言う機能は、コンパイラが対応して居なければならない。マイクロソフトやインテル製コンパイラで対応して居るようだが、高価だったり、Linux では使えなかったり、AMD の CPU に対応して居なかったら嫌だな・・と思って居たら、ごく最近 gcc でも OpenMP に対応したようである。

今年の5月にリリースされた gcc 4.2 から、OpenMP に正式対応したらしい。残念ながら今年4月にリリースされた Debian Linux etch の gcc は 4.1 である。

そこで、まず、最新の gcc をインストールするところから始める。非安定板の sid には、gcc 4.2 のパッケージがあるようだが、不安なので、ソースから構築することにした。

なお、32ビット環境の Debian にはインストールできたが、64ビット環境だとエラーが出て構築できなかった。従って、以降の話は 32ビット環境での話である。

まず、GCCソースコードの在処から、gcc-4.2.1.tar.bz2 をダウンロード。

$ cd ~/work
$ tar jxvf gcc-4.2.1.tar.bz2
$ cd gcc-4.2.1/
$ mkdir dist;cd dist
$ CONFIG_SHELL=/bin/bash; export CONFIG_SHELL
$ ../configure --prefix=/usr/openmp --enable-languages="c,c++"
$ make
$ su
# mkdir /usr/openmp
# make install
# cd /usr/openmp/bin/
# mv c++ c++-4.2.1
# mv cpp cpp-4.2.1
# mv g++ g++-4.2.1
# mv gcc gcc-4.2.1
# mv gccbug gccbug-4.2.1
# mv gcov gcov-4.2.1

残念ながら、構築に成功したのは、32ビット環境だけだ。64ビット環境だと、libc.a libc.so が無いと言ってエラーで止まる。あるのだが。

/etc/ld.so.conf に下記の一行を追加する。

/usr/openmp/lib

その後、次のコマンドでライブラリーを設定する。

# /sbin/ldconfig

~/.bashrc に下記の一行を追加する。

export PATH=/usr/openmp/bin:$PATH

上記のような方法だと、gcc 4.2 は、/usr/openmp/  の中にインストールされる。アンインストールする時は、/usr/openmp/ ごと消してしまい、PATH や ld の設定を戻すこと。

・サンプルプログラム その4:testDualCore04.c

コンパイルは簡単で、次のようにオプション「-fopenmp」を付けるだけだ。

$ gcc-4.2.1 -fopenmp -o testDualCore04 testDualCore04.c
$ ./testDualCore04.c
2007年 10月 1日 月曜日 19:34:48 JST
3.141593
2007年 10月 1日 月曜日 19:34:58 JST

システムモニターで見ながら、プログラムを走らせると、面白いように2つの CPU の使用負荷が上がる。もちろん、無駄に CPU が使われて居る訳ではなく、シングル CPU での計算の2倍の速度だ。

先のプログラムの「#」で始まる一行は、続く「for 文」を複数の CPU コアに処理を振り分ける事を意味する。

今回の円周率の計算は、極めて並列計算に合った特殊な例かもしれない。しかし、OpenMP を使うと意外に簡単にマルチコアを有効に使った並列計算プログラムが作れることが判ったことが大きな収穫だ。

注意

ブログのコンテンツの内、「告知」など時期よって情報価値が無くなるのは除いてある。また、コンテンツに付いたコメントは書き込み者に著作権があるものと判断し、ここに持ってきていないので、コメントを見るときは、元々のブログコンテンツを参照してもらいたい。

その他、ブログ発表後、コメントなどの内容を反映するなど、内容を変更しているものもあるので、注意してほしい。