OpenMP 実習資料

OpenMP 実習資料
2013-09-17 山内長承
2013-11-11 レポート期限訂正
1.実習環境
1.1 実習用サーバーと Linux
情報科学科の実習用サーバー
venus.is.sci.toho-u.ac.jp (Linux マシン、以下 venus と呼ぶ)を使う。 Linux の使
い方は2年次春学期の「UNIX とネットワーク」である程度知識があるものと想定する。 使い方に自信がない学生は自
習して欲しい。
「UNIX とネットワーク」で挙げている参考書は
参考書:
「はじめての UNIX 入門」 小林真也監修、近藤光志、阿萬裕久、木下浩二共著、森北出版。
参考書:
「UNIX という考え方」
Mike Gancarz 著、芳尾桂 監訳、オーム社。
参考書:
「新版 明解C言語 入門編」 柴田望洋著、ソフトバンククリエイティブ。
図書館にはその他にも Linux の入門書がいろいろと置いてある。
1.2 ユーザ ID とログイン
Venus へのログインは、実習室からでもインターネットからでも可能である。Linux を文字端末モードで使うので、手元
の PC 上に「端末エミュレータ」というソフトが必要である。何でもよいが、実習室の Windows PC では TeraTerm という
ソフトが使える。使い方は、ネット上で「teraterm
使い方」ぐらいで検索するとたくさん出てくる。
ユーザ ID とパスワードは、情報科実習室で使う Windows 用の ID 番号とパスワードが共通で使える。
1.3 ソースプログラムファイルの作成
ソースプログラムのファイル(ソースと呼ぶ)は、テキストエディタで編集作成しなければならない。Linux 上で編集す
ることもできるが、文字端末ではやりにくいことが多い。情報科実習室の端末 PC では、Linux 上のファイルを、あたか
も手元の Windows PC 上にあるかのように見せているので、それを Windows 上の編集ソフト(テキストエディタ、たとえ
ば秀丸)で編集することができる。但し、漢字コードが違う(Windows では Shift-JIS、Linux 上の標準は UTF-8)ので、
漢字(全角のスペース等も)を含むファイルの編集は十分な注意を要する。間違った漢字コードを用いると、コンパイル
時に予想しない動作をすることがある。
情報科実習室以外の PC から使う場合は(自宅の PC からも使える)、TeraTerm (Pro) の他に、WinSCP というフリーソフ
トを導入しておくとよい。これによって、手元の Windows PC 上で作成したファイルを、Linux サーバーに、容易に転送
することができる。この時も、漢字(全角文字)を使わないこと。なお、WinSCP を用いた、結構便利なトリックがある
ので、興味のある人は相談して欲しい。
2.
コンパイル環境・実行環境
Linux サーバー venus.is.sci.toho-u.ac.jp 上で、Cコンパイラ gcc を使って、OpenMP のコンパイルをすることがで
きる。但し、教科書 p21 にあるように、コンパイラのオプションとして -fopenmp を指定する必要がある。具体的には、
ソースコードを含むファイル
hogehoge.c をコンパイルするのであれば、コマンドラインに対して
gcc -o hogehoge (-lm など必要な追加指定) -fopenmp hogehoge.c
のようにする。-o hogehoge はコンパイラ出力(=実行ファイル)を hogehoge にせよという指定、-lm は数学ライブラ
リ(sine とか)を呼び出す指定。
コンパイラのバージョンは、
gcc -v とすると出力される。
コンパイラ gcc によって、実行可能ファイルが作られる。そのファイルの名前を指定しなければ a.out になり、オプシ
ョンとして -o hogehoge と指定すれば hogehoge になる。ここで hogehoge は自分の好きに選んでよい。これによって得
られた実行可能ファイルは、コマンドラインで hogehoge のようにそのファイル名だけを指定すると実行する。
なお、OpenMP のプログラミングの詳細は、教科書等を参照すること。
1
3.
実行中の確認
並列プログラムが実際に並列に実行されているところを確認する手段として、もし並列実行が目で見えるほど長い時間持
続するのなら、top コマンドで確認できる。並列プログラムを実行させるための TeraTerm ウィンドウに加えて、もう1
つ top コマンドでプロセッサの使用状態を常時監視するための TeraTerm ウィンドウを開く。Linux では同じユーザが複
数の端末でログインして構わない。
監視する側の TeraTerm の中で、Linux のコマンドとして top を起動する。コマンドプロンプトに対して top とキーイン
して Enter を押す。その表示が出た後、キーボードで 1
(数字の1)を押すと、右図のように CPU の一覧とそれ
ぞれの時間割合(*.*%us, *.*sy, *,*ni …)が表示され
る。(通常、TeraTerm のウィンドウは 24 行なので、1を
キーインすると「表示のための行数が足りない」
(Sorry,
terminal is not big enough)というメッセージが出る。
この時は TeraTerm ウィンドウの角をマウスでつかんで引
っ張れば、大きくできる。CPU が 32 個なので、35 行ぐら
い以上にすればうまく表示されるだろう。) 表示内容の
詳細は top コマンドのマニュアルを見てほしいが、us は
ユーザプログラムでの時間の割合、sy は OS を実行してい
る時間の割合、id はアイドル状態にある時間の割合であ
る。何もしていないときは、ほとんどの CPU は 100%id つ
まりアイドル状態にある時間が 100%で、時々1つか2つ
の CPU が何%かの us や sy の時間があることが見えるだろ
う。これはバックグラウンドの管理ジョブが動いたり、
実習室 PC からのファイルのアクセスなどが起こっている
からである。Top コマンドを修了するには、文字 q をタイ
プインすればよいし、それでうまく行かなければ、コン
トロールキーを押しながらcを押す(Ctrl-C と書く)とコマンドを修了する。
右図は 28 台の CPU を使った時の表示である。28 台がユーザアプリケーション(us)をほぼ 100%実行しており、4台の CPU
がアイドルであることがわかる。
4.実習課題
課題4A とにかく並列実行させるプログラム
下記のプログラムを venus の上で作成し、コンパイルし、実行してみよ。その時、top コマンドで CPU が並列に動作して
いることを確認せよ。
/*****************************************************/
/* Comopile with gcc -o openmptest -lm -fopenmp
*/
/*****************************************************/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <time.h>
main(int argc, char *argv[]) {
int maxcount = 2000000;
/* Number of loop execution */
2
int numthreads = 32;
/* Number of threads */
int i, c;
struct timeval tv_start, tv_end;
double s = 1.7;
omp_set_num_threads(numthreads); /* See OpenMP manual */
gettimeofday(&tv_start, NULL);
/* Start timer */
for (i=0; i<numthreads; i++) {
#pragma omp parallel for
/* parallel execution */
for (c=0; c<maxcount; c++) {
s = sin(s-(int)(s));
}
}
gettimeofday(&tv_end, NULL);
/* Stop timer */
fprintf(stderr, "time=%8.6f\n",
(double)(tv_end.tv_sec-tv_start.tv_sec)+(double)(tv_end.tv_usec-tv_start.tv_usec)/1000000.0);
}
時間測定は「壁掛け時計」によって行っている。プログラム中の gettimeofday 関数はその時点の(壁掛け時計の)時刻
を取り出す。データの形式は struct timeval で、その要素として tv_sec(時刻のうち秒単位以上の桁)と tv_usec(時
刻のうち秒より下の桁でマイクロ秒までの桁)を持っている。つまり時刻が 123.4567 秒であれば、tv_sec は 123 であり、
tv_usec は 456700 になる。また、壁掛け時計は UNIX 時刻(1970 年 1 月 1 日 0 時 0 分からの秒数)で刻まれている。細か
くはネット等で調べてほしい。
このプログラムの本体の、s = sin(s-(int)(s)) は、何も意味がない無駄な計算をしている。変数 s(double 型)から s
の整数部分 (int)(s) を引いて小数部分だけにし、それの正弦 sin を計算して次の s としている。
プログラムが正常に動作したら、次にスレッドの数 numthreads の初期値を 32 から様々な値に変更して何回か測定し、
スレッド数と時間との関係をグラフを描いてみよ。その時、縦軸は時間の代りに、時間の逆数(1/time)=加速率を取る
と、スレッド数を増やしたときに何倍に処理性能が増えたかを見ることができる。16 スレッドで 16 倍に、32 スレッドで
32 倍になるだろうか?
(アムダールの法則を思い出してみよ)
課題4B 区分求積による円周率πの計算
1)区分求積について調べよ。
2)教科書の44ページ、リスト2-7のプログラムについて、文単位で何をやっているかを説明せよ。
3)venus 上で実行し、結果を求めよ。
4)num_steps を様々な値に設定し、求めた pi の値に何が起こるか観察し、起こった現象を説明せよ。
5)課題4Aと同様の方法で、スレッド数を様々に変更し、それによって処理性能がどう変化するかをグラフ化せよ。
課題4C 配列要素の和の計算
逐次プログラムで書けば、配列 A[i] の要素の和は、
int sum = 0;
for (int I = 0; I < N; i++)
sum = sum + A[i];
で書かれるだろう。
(配列 A[i] の内容は別途初期化してあるものとする。プログラムを試す時は自分で初期化せよ)
これを並列に実行することを試してほしい。
3
1)このままで for ループの自動並列化をするとどうなるだろう?
2)もっと並列化できるように工夫してみよう。どれだけ実行時間が短くなるか?(平行コンピューティング技法参照)
実行時間が短いので、壁掛け時計では測定できないであろう。このプログラムの外側に繰り返しループを書いて、非常に
多くの回数同じことを繰り返して測定してみよ。
【レポート提出】 上記の課題を試し、簡単なレポートをまとめて提出せよ。期限は演習終了後1週間(11 月 25 日 12
月2日に訂正)とする。実験の内容と結果、および結果に対する評価・考察を報告して欲しい。
4