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

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

いつ迄もグダグダとコンピュータを語ってもしょうも無いので、そろそろ本命の高速計算をやってみる。

いきなり有人小惑星探査の軌道解析を走らせても、デュアルコアに対応したプログラムでは無いので意味が無い。

まずは、小手調べとして、比較的簡単な計算でデュアルコアを活したプログラムの作り方を研究してみた。

課題としたのは、円周率の計算だ。図で示した数式のように計算して円周率を求める。この計算式は、古くからある方法で、式自体は簡単だが、多数の桁を求めると非常に時間がかかる方法だ。現在、円周率の多数桁を求めるためには、もっと良い計算式を使って高速に求めて居る。

今回は、円周率を求めること自体が目的ではなく、むしろ沢山の計算をさせてみたいので、この式を使った。全く同じ計算をシングルコアやデュアルコアにさせて、効果を試そうと言う訳だ。

2つあるコアに、一つおきの項毎に計算させ、両方の計算が終わった後、集計しようと言うわけである。

さて、実際にデュアルコアを効果的に使うためのプログラムは、どう作れば良いのだろう。

いろいろやってみて、何とかなったのだが、成功だけを示すよりも、失敗事例も示した方が役に立つかも知れないので、失敗も含めて報告する。なお、この後、特に明言されていなければ、プログラムを実行した環境は、Athlon64 X2 4200+ Debian Linux etch の64ビット環境でマルチコア対応カーネルである。

マルチスレッドを使ってプログラミングすると、スレッド毎に CPU コアが割り当てられると聞いたので、ruby のマルチスレッド機能を使ってプログラムしてみた。

・失敗プログラム その1:testDualCore01.rb

プログラム自体は、動くには動くが、マルチスレッドでもシングルスレッドでもパフォーマンスが同じだ。システムモニターで見ると、 CPUコア は一つしか使っていない。

ネット上で調べると、ruby の最新バージョン(1.8.x)では、ネイティブ・スレッドに対応しておらず、ソフトウエアでエミュレーションしているような状態だないそうだ。ネイティブ・スレッドの対応は、次のバージョンである 1.9 かららしい。

ruby によるマルチスレッドはあきらめて、 C++ でのスレッドを使おうと思ったのが、次のプログラムである。

・失敗プログラム その2:testDualCore2.cpp

このプログラムを走らせた状態をシステムモニターで見ると、CPUコアが2つとも100%使われている。

「やったね」と思って、パフォーマンスを測るのだが、何処かおかしい。

なんと、スレッドを使わず、CPUコアを一つだけ使って計算している方が、マルチスレッドを使った場合よりも速いのだ。

どうやら、単純にマルチスレッドを使ってプログラミングしただけでは、有効にデュアルコアを活用できないようだ。(無駄に活用することはできるが)

マルチスレッドは、スレッド間でメモリを共有できるのが良いのだが、それが逆に悪さをしているのかも知れない。二つのコア間で、メモリの同期を取る必要があるなら、動作はむしろ遅くなる可能性がある。

本来、マルチスレッドを使って上手くプログラミングすれば、デュアルコアを有効に使える筈だ。この時は、明確に使用するメモリを分ける必要があるのだろう。

どうやれば、スレッド間でメモリを明確に分けるのか、調査するのも面倒になったので、fork を使って、プロセス自体を分離することにした。

これが次のプログラムである。(プログラム中パイプを使って通信しているので、「fork」ではなく「open」で子プロセスを起動している)

・成功プログラム その3:testDualCore03.rb

再び、ruby を使っている。プログラムを見れば判るが、引き数に何も入れなければデュアルコア対応、引数に「-1」を入れるとシングルコアプログラムである。

このプログラムは上手く動作した。

次がその結果である。

・モバイルセレロン 450MHz Linux sarge i386(32bit環境)

 ・シングルコア用 334秒 デュアルコア用 334秒

・Athlon64 X2 4200+ Xp Home (ruby はRuby-mswin32)

 ・シングルコア用 68秒 デュアルコア用 34秒

・Athlon64 X2 4200+ Linux etch i386 (カーネル名 486 32ビット環境 シングルコアのみ)

 ・シングルコア用 54秒 デュアルコア用 57秒

・Athlon64 X2 4200+ Linux etch i386 (カーネル名 686 32ビット環境 マルチコア対応)

 ・シングルコア用 58秒 デュアルコア用 29秒

・Athlon64 X2 4200+ Linux etch amd64 (カーネル名 amd64 64ビット環境 マルチコア対応)

 ・シングルコア用 57秒 デュアルコア用 29秒

とまあ、こんな結果になった。

総括すると、次のようになる。

・XP Homeよりも Linux の方が、やや速い。

・マルチコアに対応したOSだと、約2倍の速度が得られる。

・シングルプロセスのみなら、むしろマルチコア非対応のカーネルの方が速い。

・32ビットと64ビット環境では、有意な差は無い。

・デュアルコア有効状態のAthlon64 X2 4200+ は、モバイルセレロン 450MHz の約 10 倍速い。

ところで、ついでにYouTube で動画を再生しながら、プログラムを走らせてみた。

・Athlon64 X2 4200+ Xp Home (ruby はRuby-mswin32)

 ・シングルコア用 73秒 デュアルコア用 39秒

・Athlon64 X2 4200+ Linux etch i386 (カーネル名 686 32ビット環境 マルチコア対応)

 ・シングルコア用 60秒 デュアルコア用 37秒

・Athlon64 X2 4200+ Linux etch amd64 (カーネル名 amd64 64ビット環境 マルチコア対応)

 ・シングルコア用 62秒 デュアルコア用 33秒

シングルコア用プログラムでは、ほとんど劣化していない。これは、CPUコアの一つで動画を再生、もう一つで円周率の計算をしているからだ。

流石にデュアルコア用プログラムでは、多少遅くなっているのだが、これは仕方が無い。

動画の方だが、XP Home でのデュアルコア用プログラムを除いて、全く問題無く再生できた。

それに対して、XP Home でのデュアルコア用プログラムの時は、グダグダで、飛び飛びの再生で、頻繁に停止する。

動画再生中の時のデュアルコア用プログラムの時、初めて、64ビットと32ビット環境の差が出た。

ところが、これは、グラフィックカード性能によるものである。現状、32ビット環境では、グラフィックカード専用ドライバのインストールに成功しておらず、64ビットのときのみ、GeForce ドライバを使っている。

64ビット環境で、32ビットとの時と同じく VESA ドライバーを使うと、動画再生時に 32ビットと同じ性能になる。

と言う訳で、やっとデュアルコア用プログラミングのやり方が少し判って来た。

プロセスではなく、スレッドを使った方が、オーバーヘッドが少ない筈だが、そっちの方は今後の課題である。

ところで、何故、ruby を使っているのか、不思議に思う人もあるかも知れない。

高速の計算なら、普通、コンパイラ言語だろう。

私の場合、本当に高速なところは、CやC++、フォートランと言ったコンパイラ言語を使うのだが、多数のパラメーターを振って、そのプログラムを呼び出すのに ruby を使うことが多い。小惑星探査軌道計算も、そうである。

今度は、小惑星探査の軌道解析を、デュアルコアを有効に使って計算したいと思う。

注意

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

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