« 告知 | Main | 時間の無駄 »

October 01, 2007

デュアルコア対応プログラミング 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 を使うと意外に簡単にマルチコアを有効に使った並列計算プログラムが作れることが判ったことが大きな収穫だ。

|

« 告知 | Main | 時間の無駄 »

Comments

またひどいアルゴリズム!
収束が遅くて有名な級数を使ったのは性能を見るためとして、分数の引き算で桁落ちするし、総和でも大きい項から足してるから桁落ちする。(引き算の桁落ちの影響は、これで無くなりそうだ)
並列計算なら、arctan 2つを同時に計算する方法が良いのでは?(もちろん、和は小さい項から)
HITAC 10 のアセンブラ (自分で機械語にしてたけど) でπを1万桁計算して、やたらと時間がかかったのは昔話。

Posted by: hirota | October 19, 2007 01:04 PM

まあ、元々、収束が悪くて、デュアルコアの効果が判る例を選んだんですから、勘弁してください。
もっと、良いアルゴリズムを選ぶと、デュアルコアの効果どころか、シングルコアでも、あっと言う間に収束するので、差が出ないのですよ。

Posted by: 野田篤司 | October 20, 2007 08:46 PM

Post a comment



(Not displayed with comment.)


Comments are moderated, and will not appear on this weblog until the author has approved them.



TrackBack


Listed below are links to weblogs that reference デュアルコア対応プログラミング OpenMP 編:

« 告知 | Main | 時間の無駄 »