ノート/ノート

2009-07-03 生命科学系のプログラムの並列化の動向

いくつかのページが面白かったので、リンクを残しておこう
GPGPU & CHARMM で検索

IBM Cell & CHARMMで検索

NAMDのホームページ

2009-06-16 追記 (マルチコアと並列プログラミング)

2007-04-16

この研究は、当面「卒論レベル」。何か新しいことが出てくるかどうかは まだわからない。

何をやるのか

やりたいこと: 現在コンピュータで(直列に)処理されているために、時間がかかって「困る」ような問題がある。それを並列実行して、早くする。

背景: (1)「マルチコア」のCPUが手ごろな値段で手に入るようになった。(4コアだと4並列、8コアだと8並列、かける CPU数(2つとか4つとか))
    (2)大学にあるPC教室のPCを、空いている時間に使って、並列実行できる。(90台使えれば90並列)

先行研究: 山のようにある。並列処理は古くからの話題。
 ポイント1: N台のCPUがあったとしても、なかなかN倍速くならない
    (実は今までは並列で稼ぐよりCPUクロックを加速する方が簡単で安かった)
    どれだけ速くなるかは、プログラムの性質による。このあたりの研究はたくさんある。
    既に並列化されているプログラムもいくつか(かなりたくさん)ある。
 ポイント2: 「並列化」は人手vs自動があり、人手は一般には大変。(他方問題によっては自明なものも多い) 自動化は今でも研究ネタ(たとえば吉田研)

もう一度「やりたいこと」: とにかく並列にして速くできる問題を並列実行して、役に立ってみたい。

環境など

環境: 昨年度末に買ったHPのサーバーは4コア×2CPUで8並列可能。

OS: Linuxをインストール済み。プロセスレベルの並列処理は既に可能。後で例を示す。

並列ミドルウェア: プログラムを並列分割し、簡単に実行させられるプラットフォーム(ミドルウェア)がいくつかある。大別すると
  共有メモリ型(変数共有型)モデル: ミドルウェアとしてOpenMPが有名。
  メッセージ交換型モデル: インターフェースとしてMPIがあり、その実装としてフリーのMPICH/MPICH2がある。
モデルとして比較すると、共有モデルは密な相互作用(細粒度の並列)が可能なのと、コンパイラが自動並列化するようなことが可能。たとえばIntelのコンパイラの-parallelオプション。ハードウェアの制約から並列度はそれほど大きくならない(せいぜい数十)
メッセージモデルはメッセージ交換に時間がかかるので疎な相互作用(大粒度の並列)に向く。その代わり並列度は大きく出来る。(TCP/IPを使うのが流行だが、それだとほとんど無限まで可能。世界中のコンピュータをつなぐことも可能。)ネットワーク遅延を短縮する工夫も昔あった(Myrinetが有名)。ギガビットイーサの場合、転送は早いがセットアップに時間がかかると言われる。

この辺の記述へのポインタをここに挙げる

レベル−1の予備実験~

折角買ったサーバーなので、本当に並列実行できるか試してみた。
CPUでの仕事だけ(ほとんど、だが)をするプログラムを作る。何でもいいが、余りに自明なプログラムだとコンパイラが賢いので命令を最適化=省いてしまうので要注意。プログラムは

#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

main(int argc, char **argv) {
  int i, maxi;
  double x;
  char bufin[256];

  if (argc !=2) {
    fprintf(stderr, "usage: paratest <maxi>.  maxi=~~10000000\n");
  } else {
    maxi = atoi(argv[1]);
    if (maxi<=0) {
       fprintf(stderr, "maxi <= 0\n");
    }
  }
  for (i=0; i<255; i++) bufin[i]='\0';
  x = 0.0;
  for (i=0; i<maxi; i++) {
    x = x + sin( (double) i/maxi );
  }

  read(0, bufin, 256);
  printf("%s", strcat(bufin, "a"));
  fprintf(stderr, "%s", strcat(bufin, "a"));
}

コンパイル時に-lmが必要。(Math Libraryを使っているため)

このプログラムをプロセスとして、並列実行させてみる。シェルレベルで並列起動、つまりcshellでの「&」や「|」を使う。最初に「&」を試したが、終了が判定しにくいので、「|」(パイプ)を使うことにする。
決めた数のプロセスをパイプでつないで並列に起動する。最後にパイプを通じてメッセージが最後のプロセスに行き着いて、終了がわかる。このシェルスクリプトは

#!/bin/csh
set N = 100000000

# Case of 8 processes
echo "" | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $ N | pipebody $N | pipebody $N

# Case of 12 processes
#echo "" | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pipebody $N | pebody $N | pipebody $N

# Case of 1 process
#echo "" | pipebody $N

のように書いた。

これを実行させる時に、コマンドtimeを使う。最近のLinuxのtimeコマンドは、

The default format string is
         %Uuser %Ssystem %Eelapsed %PCPU (%Xtext+%Ddata %Mmax)k
         %Iinputs+%Ooutputs (%Fmajor+%Rminor)pagefaults %Wswaps

ということで、昔ながらの real ... user ... sys ... という形式でないが、却って情報は分かりやすい。

結果は次のようになった。

          user   system elapsed  PCPU~
プロセス1つ:   9.720u  0.028s  0:09.74  100.0%   0+0k 0+0io 0pf+0w~
プロセス4つ:  38.814u  0.036s  0:09.75  398.3%   0+0k 0+0io 0pf+0w~
プロセス8つ:  77.476u  0.020s  0:09.76  793.9%   0+0k 0+0io 0pf+0w~
プロセス9つ:  87.301u  0.040s  0:14.62  597.4%   0+0k 0+0io 0pf+0w~
プロセス12:  116.407u  0.028s  0:15.93  730.8%  0+0k 0+0io 0pf+0w~
プロセス16:  155.189u  0.044s  0:19.54  794.3%  0+0k 0+0io 0pf+0w

この環境では1つのプロセスが食うCPU時間は9.72秒程度であり、プロセス数を1⇒4⇒8まで増やした時にuser time(=プロセス総時間)は38.81秒=4×9.70秒、77.48秒=8×9.685のように増えているが、elapsed time(=端末で見ている時間)は3つとも9.74〜9.76秒でほとんど変わらない。つまり8並列まで実現できている。そのときのCPU percentage (PCPU) は398.3% 793.9%と、ほとんど並列度と同じ値を示している。

ところが、9プロセスを越えたところで、9つ目のプロセスは余ってしまい後から実行されるわけで、実際 elapsed time が(9.75秒から)14.6秒に伸びている。完全に2倍にならない理由は、おそらく外側のオーバーヘッドがあるためだろう。そして、9プロセス⇒12プロセス⇒16プロセスと増やしても elapsed time は多少増えるだけで倍増はしていない 14.6秒⇒15.9秒⇒19.5秒(16の場合多少微妙かも。大丈夫かな?)

ということから、8並列が実現されているらしいことは分かった。

次のステップ

考えられる方向として、


添付ファイル: file070418.ppt 323件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-07-05 (日) 17:00:30 (2879d)