Top Banner
令和 2 年度 MICS 実験第 2 2 ラウンド (2e) 「レイトレーシングの並列処理」 : ([email protected]) TA : ([email protected])
48

「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf...

Apr 02, 2021

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

令和2年度 MICS 実験第2

第2ラウンド (2e)

「レイトレーシングの並列処理」

担当 : 龍野 智哉([email protected])

TA : 鎌田 彬史([email protected])

Page 2: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

This page intentionally left blank.

ii

Page 3: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

目次

1 実験の進め方 1

1.1 実験計画 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 実験時の注意 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 レポート提出方法について . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.4 推薦参考書 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 レイトレーシングで 3次元オブジェクトを描いてみよう 6

2.1 画像の表現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.2 レンダリング (rendering, 表示技法) . . . . . . . . . . . . . . . . . . . . . . 6

2.2.1 陰面消去 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.2.2 光源 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.2.3 Lambertの余弦則 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.2.4 環境光 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.3 反射光の追跡 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.4 透明感 (屈折: Fresnelの公式) . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.5 レイトレーシングプログラムの使い方 . . . . . . . . . . . . . . . . . . . . 10

2.6 第一回課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Hello MPI World! 12

3.1 Hello World を動かしてみよう . . . . . . . . . . . . . . . . . . . . . . . . . 14

3.2 MPI プログラムの書き方の初歩の初歩 . . . . . . . . . . . . . . . . . . . . 15

3.2.1 プロセスのランク . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3.2.2 通信 Send/Recv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3.3 集団通信 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.3.1 ブロードキャスト (Broadcast) . . . . . . . . . . . . . . . . . . . . . 19

3.3.2 スキャッタ (Scatter) . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3.3 ギャザー (Gather) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3.4 リデュース (Reduce) . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4 CGプログラムの並列化指針 21

4.1 逐次版レイトレーシングプログラム . . . . . . . . . . . . . . . . . . . . . . 21

4.2 ファイル単位の単純な並列化 . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.3 マスター・スレーブ方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4.3.1 仕事の分割と割当て (静的な割当て方式) . . . . . . . . . . . . . . . 24

4.3.2 仕事の割当て (タスクプール方式) . . . . . . . . . . . . . . . . . . . 26

5 CG 並列処理での通信の効率化 27

5.1 仕事の分割 (タスクプール方式)の続き . . . . . . . . . . . . . . . . . . . . 27

5.2 データ送受信と計算のオーバーラップ . . . . . . . . . . . . . . . . . . . . 28

5.3 ダブルバッファ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

5.4 第二回課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

iii

Page 4: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

6 CG 最終課題 33

6.1 第三回課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

A (付録)レイトレーシングデータの記述について 34

A.1 視野の定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

A.2 照明環境の定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

A.3 物体の属性の定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

A.4 物体の構造の定義 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

A.5 画像生成の対象とする物体の定義 . . . . . . . . . . . . . . . . . . . . . . . 38

A.6 「ことり」を例に簡単な説明 . . . . . . . . . . . . . . . . . . . . . . . . . 38

B (付録)レイトレーシングのモチーフデザインの仕方 39

C (付録) OpenGL との関連 40

C.1 OpenGL を用いる上での問題点 . . . . . . . . . . . . . . . . . . . . . . . . 40

C.1.1 計算途中の画像をディスプレイ表示するには? . . . . . . . . . . . 41

D (付録) 立体視にチャレンジ 42

D.1 立体視画像の仕組み . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

D.2 立体視画像の作り方 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

iv

Page 5: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

1 実験の進め方

1.1 実験計画

MICS 実験第 2の課題は「レイトレーシングの並列処理」です。全 7 回の実験予定表を下に示します。はじめの 2 回でレイトレーシングプログラムと MPI (Message Passing

Interface)の簡単な使い方に慣れてもらい、CG (Computer Graphics)の並列化に取り組んでいってもらいます。途中いくつか技術的な内容を挟んでいきますが、並列処理一般の項目や MPI 特有のものなどを含みます。これら全てを用いて最終的な CG の並列処理ができるようになりますので、途中の内容も手を抜かないように心がけてください。基本的な内容から実習を行って各課題にトライし、実験内容ごとにまとめのレポートを提出してもらいます。原則: 各課題終了後の 1 ~ 2 週間以内をめどに締め切りを設定するので, 締め切りまでにレポートを提出してください。また、最終課題 (並列 CG)の締め切りは他の物よりも長くラウンド終了後 3 週間とします。完成度の高く内容も充実したレポートを期待しています。なお、単位認定の必要条件は全 3 編のレポート提出です。期日に遅れることなくレポートを提出することが 3 課題完走の秘訣です。期間が 1 ヶ月ほどしかありませんので、テキストを見ながら下に示した日程よりも先に進めておくことが望ましいでしょう。本実験の成績はレポートの内容を最重視します。また、最終課題の CG 作品についても感動的な作品には高い評価を与えますので、プログラミングに自身のない人は CG 作品に力を注ぐと良いでしょう。下の表はあくまで予定です。途中で変更することもありえます (締め切りが早くなることはありません)ので、本実験のウェブサイト

http://www.im.uec.ac.jp/~tatsuno/lectures/exp2/

をチェックするようにして下さい。実験予定表で自習となっている日は特に説明は行いません。各自直接 CED にログインして実験を始めてください。

表 1: MICS 実験第 2, 龍野班第 2ラウンド (2e)日程回数 (実施日) 内容 備考

第 1回 (11/2) オリエンテーション 課題 1

レイトレーシングの初歩 (レイトレーシング基礎)

第 2回 (11/4) 並列処理とは MPI の第一歩Send/Recv と通信モデル

第 3回 (11/9) CG プログラムの並列化指針 課題 2

(マスター・スレーブ方式) (MPI とマスター・スレーブ処理)

第 4回 (11/11) CG 並列処理での通信の効率化第 5回 (11/16) 自習第 6回 (11/18) 自習第 7回 (11/25) 自習 課題 3 (並列CG)

1

Page 6: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

1.2 実験時の注意

今年は MICS 実験を遠隔で行うことになりました。本実験で扱う並列処理を行うためには、複数の計算機資源を同時に必要とします。自宅で複数のマシンを用意できる人は稀でしょうから、遠隔で CED に接続してもう必要があります。まず CED のウェブサイト

https://www.ced.cei.uec.ac.jp/

から「自宅で CED のデスクトップ (GUI) を利用する初期設定・確認方法」にしたがってVNC を設定し、GUI 環境が使えるように準備して下さい。Linux に詳しい人は ssh で X

を飛ばすことも考えられますが、本実験で扱うコードは OpenGL を使うため、設定が煩雑になるおそれがあります。自信のある方は練習がてらトライしてみても良いと思いますが、遠隔でのサポートは困難ですので、自己責任でお願いします。MICS 実験では端末室の計算機を利用する学生が多数いるため、好きなだけ計算機台数を増やして計算させるわけにもいきません。したがって、実験中は他の利用者も使っている端末を共用することになります。そのことを特に意識して、他の利用者の妨げにならないように以下のことに注意してください。

並列プログラムが異常終了した場合に、プロセスが残っていないか確認すること。プロセスが残っていた場合は kill する。リモートマシン上のプロセスの確認は

ssh hostname ps -u username

で行い、ssh hostname kill -9 procid

もしくはssh hostname killall -9 programname

で killする。

以下に、各自が割り当てられて VNC 接続するマシンに加えて、実験時間中に我々が共同で使える端末 18 台のリストを示します:

purple30 purple33 lemon03 lemon06 lemon09 lemon20

lemon21 lemon24 lemon27 lemon30 lemon33 lemon36

blue01 purple01 yellow03 yellow06 red03 red07

上記に加え、土日、早朝には以下の端末 30 台も使えます:

red03 red06 red09 red12 yellow06 yellow09

yellow12 blue03 blue06 blue09 purple03 purple06

purple09 purple12 lemon12 lemon15 lemon18 blue01

blue15 blue18 blue21 blue24 blue27 blue30

blue33 purple15 purple18 purple21 purple24 purple27

これらの使い方についてはまた後で並列処理を行う際に説明します。

2

Page 7: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

CED機器配置

エリア 2 yellow エリア 3 blue エリア 4 purpleエリア 1 red エリア 5 (ハード実験用)

図 1: CEDのエリア分け

それぞれのエリアごとに英語で 1色の色が振られていて、エリアに配置されている端末のホスト名は「色+数字 (10 進 2 桁)」と決まっています。

3

Page 8: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

1.3 レポート提出方法について

レポート出題するページでもそれぞれのレポート提出方法を指示しますが、ここでは全てに共通するルールについて記しておきます。まず、提出時には各課題ごとにディレクトリを作成し全てのソース、実行ファイル、実行結果を格納し、tar コマンドで固めて添付ファイルとしてレポートと一緒に提出してください。レポートは LATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。

電子メールによるレポート提出先は [email protected]

もしファイルが大きすぎてメールサーバにはじかれた場合には、レポートの pdf ファイルのみを電子メールで提出することとし、そこに CED のアカウント名とレポートの問題を解いたディレクトリを記して下さい。ただしこの場合、自分以外の人がディレクトリを見れるよう、パーミッションを適切に設定すること (デフォルトでは見れるようになっているはずです)。レポートには実験第二の第 2ラウンド (2e)課題であることを明記した表紙をつけ、課題番号とレポート、そしてどのディレクトリにプログラムとその結果を保存したかを電子メールに示してください。レポートの書き方が悪い学生には再提出を求める場合があるので、以下のチェックリストを参考にして作成に臨むこと。

提出チェックリスト

1. レポートの表紙に名前、学籍番号、実験第二第 2ラウンド (2e)、課題の第何回目かを記しているか?

2. 忘れた問題はないか?

3. 各問題に対して適切な分析をしているか?

4. 作成したプログラムの説明は適当か?

5. プログラムの実行結果は書かれているか?

6. 問題に対する適切な答えが書かれているか?

7. 参考文献 (もしあれば)は書かれているか?

8. 正しいディレクトリにレポート・プログラム・実行結果一式があるか?

9. 添付ファイル (ソース実行ファイル一式)はつけているか?

10. 電子メールで提出する場合は自分に Cc (カーボンコピー)を忘れずに.

11. 提出期限を過ぎていないか?

4

Page 9: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

1.4 推薦参考書

次の文献を参考書としてあげておきます。文献 1は本実験でとりあげるCGプログラム一般について解説したものです。文献 2~4は図書館にあるので必要があれば貸りて参考にするといいでしょう。なお、文献 6は印刷すると 200ページを超えるものなので、印刷はしないで必要なときにURLにアクセスし閲覧することが望ましいといえます。他にも並列処理に関する情報がWeb上にありますので、各個人で「CG」、「並列」、「MPI」などで検索してみると良いでしょう。

1. 千葉則茂、村岡一信 : C による CG レイトレーシング, サイエンス社, 1991.

2. P.パチェコ著, 秋葉博訳 : MPI 並列プログラミング, 培風館, 2001.

3. 飯塚肇 ·緑川博子共訳 : 並列プログラミング入門 ネットワーク結合 UNIXマシンによる並列処理, (原著は Barry Wilkinson and Michael Allen : Parallel Programming,

Techniques and Applications Using Networked Workstations and Parallel Comput-

ers), 丸善, 2000.

4. W. グロップ, E. ラスク, R. ターカ著, 畑崎隆雄訳 : 実践 MPI-2 — メッセージパッシング・インタフェースの上級者向け機能, ピアソンエデュケーション, 2002.

5. William Gropp, Ewing Lusk and Anthony Skjellum : Using MPI, Portable Paral-

lel Programming with the Message-Passing Interface second edition, the MIT Press,

1999.

6. MPI Forum, MPI: A Message-Passing Interface Standard Version 3.1.

英文 HTML 形式のマニュアルにアクセスできる。

http://www.mpi-forum.org/docs/mpi-3.1/mpi31-report/mpi31-report.htm

また、ちょっと古いが日本語訳として

https://www.mpi-forum.org/docs/translations-japanese/mpi-report-j.pdf

から日本語マニュアルが取得できる。MPI の全ての仕様が MPI Forum で規定されている。

また、他に OpenGL や 3D レイトレーシングソフトについて多くの文献が出版されていますし、ホームページが存在します。興味がある諸君は参考にしてみてください。

7. OpenGL を用いた VR 実験http://www.is.oit.ac.jp/~whashimo/server/~whashimo/Article/OpenGL/

8. POV-Ray ホームページhttp://www.povray.org/

9. Rayshade ホームページhttp://graphics.stanford.edu/~cek/rayshade/rayshade.html

5

Page 10: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

2 レイトレーシングで3次元オブジェクトを描いてみよう本実験で扱う CG (Computer Graphics)は、コンピュータを使って 3 次元形状モデル (3

次元オブジェクト)を 2 次元画像に変換することを指します。人が物を見ている状態とは、光源から出た光が、反射、透過、屈折を繰り返し視点 (目)に届くということです。この光を視点から逆にたどって (光線を逆に発して)画面上の各画素の色、輝度情報を計算する手法がレイトレーシングです。2.1章から 2.4は原理部分の話をしますが、実際にはその詳細を理解しなくてもレイトレーシングプログラムを使用することはできるので読み飛ばしても構いません。2.5章を理解するようにしてください。

2.1 画像の表現

本実験では、画像は画素 (ピクセル: pixel)と呼ばれる点が長方形の 2 次元に配置してあるものとします。各画素の色を指定することで画像が決まります。各画素の色は R (red,

赤), G (green, 緑), B (blue, 青)のそれぞれの値を決めることで色が決まります (RGB方式)。R, G, Bそれぞれを 8ビット、3色で 24ビット使うと約 1600万色 (224 = 16, 777, 216)

が表現できます。各ピクセルの色情報を指定すれば画像が決まりますが、画像を画面に出力するには画像処理のための汎用画像処理ライブラリを利用することになります。X の基本ライブラリの他各種ライブラリがありますが、本実験では OpenGL (またはクローンである Mesa ライブラリ)を利用します。OpenGL は本来、 3 次元のオブジェクトの描画を支援するものですが、本実験では 2 次元画像の表示機能のみを使用します。画像のファイル保存形式は PBM, PPM, GIF, JPEG など各種存在しますが、本実験では PNG (Portable Network Graphics)形式を使用します。この形式は 24ビットフルカラーを扱うことができ、圧縮機能によりファイルサイズを小さくできる特徴をもちます。

2.2 レンダリング (rendering, 表示技法)

ここでは、視線がスクリーンと常に垂直となる平行投影について述べることとします。スクリーン上のピクセルの色を決める最も単純な方法は以下の様になります。

• (px, py) を通り z 軸に平行な直線 (視線)と、物体との交点を全て求める。

• 交点の中で最も手前の点を可視点とする。

• ピクセル (px, py) の色は可視点における物体の色とする。

• 交点がない場合は、背景色をピクセルの色とする。

2.2.1 陰面消去

物体を見るときには、物体の見えている部分と、奥の見えない部分が存在しています。CG を行う際には、計算機内で定義された 3 次元オブジェクトに対して見えない部分を検出して、見えている部分 (可視点)のみを表示しなくてはなりません。

6

Page 11: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

x

z

y

Sh-1

-Sh

-Sw

Sw-1

(0,0,1)

z0

x

z

y

方向余弦E

ピクセル(px, py, pz)

視点(vx, vy, vz)

Sh-1

-Sh

-Sw

Sw-1

図 2: 球とスクリーンの配置 (左図: 平行投影, 右図: 透視投影)

簡単のために、球体を見ることを考えます。図 2に示すように、中心 (0, 0, z0), 半径 r の球を z < 0 の方向から見ます。スクリーンの幅は 2Sw, 高さは 2Sh で、スクリーンは平面z = 0 上に原点が中心となるように置かれることとします。以後、スクリーンの z 座標 0

は省略します。一般に、点 (px, py, pz) を通り、単位ベクトル E = (Ex, Ey, Ez) に平行な直線上の点 (x, y, z) はパラメータ t を用いて

x = Ext+ px (1)

y = Eyt+ py (2)

z = Ezt+ pz (3)

と書けます。ここで E を方向余弦と呼びます。平行投影の場合は視線ベクトルは E =

(0, 0, 1) で、スクリーン上では pz = 0 を考えればよいので

x = px (4)

y = py (5)

z = t (6)

x2 + y2 + (z − z0)2 = r2 (7)

の関係式ができます。これを解くと

t = z0 ±√r2 − p2x − p2y (8)

となり、根号内が正のとき、つまり r2 ≥ p2x + p2y のとき交点を持ちます。また、t はスクリーンから物体までの距離に相当するので、式 (8)は ‘−’の符号のとき可視点を表すこととなります。ここでは球体のみを考えましたが、各種物体の形状に応じてこの様な可視点決定のルールを決めてプログラムを組みます。また、一般的には平行投影ではなく視点から放射状に視線が放出される透視投影を用います。その場合、視点を (vx, vy, vz) としたときにピクセル (px, py, pz) への視線の方向余弦 E を次のように定義して可視点を算出します。

E =

(px − vx

l,py − vy

l,pz − vz

l

), l =

√(px − vx)2 + (py − vy)2 + (pz − vz)2 (9)

7

Page 12: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

2.2.2 光源

光源は、光源の色の強さ Ip = (Ip,R, Ip,G, Ip,B) と、その方向余弦 L が与えられれば一意に表すことができます。

2.2.3 Lambertの余弦則

拡散反射物体は、あらゆる方向に均等に光を反射します。したがって、どの方向からその表面を見ても同じ明るさで見えます。この様な表面の輝度(明るさ)は Lambertの余弦則でモデル化されます。光の強さを Ip = (Ip,R, Ip,G, Ip,B), 光線の方向余弦を L (光源に向かう向きに), 物体表面の輝度を Id = (Id,R, Id,G, Id,B), 光の入射角を θ, 物体表面の単位法線ベクトルを N , 物体の拡散反射係数を kd = (kd,R, kd,G, kd,B) とすれば

Id,∗ = kd,∗Ip,∗ cos θ = kd,∗Ip,∗L ·N (10)

‘*’はR,G,Bそれぞれについて成り立つことを意味しています。ここで、L ·N < 0 のときは裏側からの光と解釈できるので Id = 0 とします。物体表面の色は、白色光を光源とした時の拡散反射係数で与えることができるので、kd の RGB 値で与えるのと同等ということになります。

2.2.4 環境光

壁や床の周囲にある物体の影は間接光 (相互反射光)のため真っ黒にはなりません。近似的に一定の環境光による拡散反射光もあるとして、それも考慮して表面輝度とします。環境光の強さを Ia = (Ia,R, Ia,G, Ia,B) とすれば

kd,∗(Ip,∗L ·N + Ia,∗) (11)

と修正すればよいこととなります。

2.3 反射光の追跡

入射角と反射角が等しいという正反射の性質を使うと、鏡面上での反射光を計算することができます。また、鏡面から視点方向に反射してくる光の色がピクセル色に相当するので、鏡面で正反射し視点に向かう物体表面の色もしくは光線の色情報がピクセルの色になります。これを求める手順を整理すると、以下の様になります。

1. 鏡面と視線の交点(最初の可視点)から正反射方向に向かう視線ベクトルを出す。

2. 再び可視点を計算するための交点計算を行う。

3. 新たな可視点の色をこれまでの陰影付けモデルから決定する。

4. その色を鏡に映りこむ色、すなわちピクセルの色とする。

8

Page 13: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

物体1

物体2

I1

θ1θ1

θ2

ks1I1

kt1I1

N

物体1

物体2

I1

θ1θ1

θ2

ks1I1

kt1I1

N

θ2

I2

図 3: スネルの法則 (左図)と目に入ってくる鏡面反射光と透過光の合成 (右図)

この手法を使うため(光線の追跡)レイトレーシングと呼ばれます。正反射した視線の視線ベクトル R は、視線ベクトルを E, 鏡面上の交点での単位法線ベクトルを N とすると

R = 2(−E ·N )N +E (12)

鏡面で反射した視線が当たった物体もまた鏡面であった場合、その鏡面で再度正反射した視線ベクトルを計算し、追跡を行えばよく、プログラムでは再帰呼び出しを使えば簡単です。ただし、反射回数が多くなったり無限反射に陥ることがあるので、実際には最大反射回数を決めておくのが普通です。

2.4 透明感 (屈折: Fresnelの公式)

ガラスなどの透明感のある物体表面では、鏡面反射に加えて、光が屈折をしながら透過することが知られています。図に示すように、物体 1 と 2 の境界面で物体 1 からの光が物体 1 への反射と物体 2 への屈折に分かれる場合を考えます。入射角 θ1, 屈折角 θ2, 物体 1,

2 の屈折率がそれぞれ n1, n2 のとき、スネル (Snell)の法則から

n1 sin θ1 = n2 sin θ2 (13)

の関係が成り立ちます。次に、物体 1 側の鏡面反射係数を ks1, 物体 2 への透過係数を kt1とすると、光 I1 のうち ks1I1 が反射角 θ1 で鏡面反射して、kt1I1 が透過することになります。光の損失がなければ ks1 + kt1 = 1 ですので、反射係数 ks1 について次のフレネル(Fresnel)の公式が成立します。

ks1 =1

2

{sin2(θ1 − θ2)

sin2(θ1 + θ2)+

tan2(θ1 − θ2)

tan2(θ1 + θ2)

}(14)

θ1, θ2 を入れ替えても同じなので、ks1 = ks2, kt1 = kt2 が成立。結果的に視点に入ってくる光は ks1I1 + kt2I2 となります。なお、屈折率は光の波長によって異なるのですが(例:プリズム)、屈折角の計算が複雑になり計算量も増加するので屈折率は一定とします。その代わりに、便宜上透過する際の透過係数 (ct,R, ct,G, ct,B)を RGB 毎に変更することをします。

9

Page 14: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

2.5 レイトレーシングプログラムの使い方

参考書のレイトレーシングプログラムは rt1, rt2 の二つに分かれています。プログラムrt1 は 3 次元オブジェクトのデータ定義ファイルを解釈して実際のレイトレーシング処理(レンダリング)プログラムで処理しやすい形式に変換します。プログラム rt2はレイトレーシングによるレンダリングを行います。本実験での並列処理の対象となるのは、rt2 の方です。今回用いる rt1, rt2 は、/home3/staff/ta000741/.ced_centos/bin/ にあります。まず、プログラムの使用方法を簡単に説明します。3 次元オブジェクトのデータは拡張子 ray のファイルに格納されているとします。ファイル名の先頭部分を foo とすれば (つまり、ファイル名は foo.ray)、まず第一段階として次の操作をします (行頭の ‘%’はプロンプトです)。この操作によって、拡張子 ray のデータファイルから、拡張子 cod のデータファイル (foo.cod)が作成されます。�� ��% rt1 foo

引き続きレイトレーシングのレンダリングプログラム rt2を実行します。rt2は沢山のオプションを指定でき、オプションを指定しない状態では計算のみをするだけで画像を取得できないので注意が必要です。rt2 -hで使用できるオプションを確認しましょう。'

&

$

%

% rt2 -h

usage : rt2 [options] base_of_filename ...

: rt2 [options] -f list_filename

options :

-h : show this help message

-v : verbose mode

-d : display image

-p : output to png file

-q : quieten and quit after all raytracing

-n : no anti-aliasing

-g : show diagnostic

-b : draw border lines

普段、一般利用者が指定するオプションは -d, -p です。試しに、/home3/staff/ta000741/.ced_centos/exp2/sample にある幾つかの ray ファイルからCG 画像を作成してみましょう (課題 1.2)。CG 画像は、データ定義ファイルを適切に作成して、時間をかけて画像のレンダリング処理をすれば素晴らしい画像を得ることができます。次に、高度なデータ定義を行った CG

画像について処理をしてみよう。想像以上に処理の時間がかかることが分かります (これを如何に速く処理していくかが次の課題になるのは簡単に理解できますね)。テキストの付録Aも読んで課題 1.3, 1.4に取り組もう。

10

Page 15: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

2.6 第一回課題

課題 1.1

レイトレーシングの原理は何か、透視投影のもとで球体を画像にすることを例にして説明せよ。

課題 1.2

レイトレーシングのプログラムを使用して

/home3/staff/ta000741/.ced_centos/exp2/sample/

の下にある幾つかの ray ファイルのレンダリングをしてみよ。

課題 1.3

床、立方体、球体を複数組み合わせた CG 画像のデータファイルを作成し、rt1, rt2 プログラムを利用して CG 画像を作成せよ。また、物体表面に様々な効果を組み合わせて、その画像の違いを比較せよ。

課題 1.4

http://www.im.uec.ac.jp/~tatsuno/lectures/exp2/ にあるギャラリーから、好きなCG 画像のファイルを選択して、その画像のレンダリングにかかる時間を測定せよ。また、サンプルファイルの kotori.ray の内容と比較して、時間がかかる原因をレイトレーシングの原理を考慮に入れた上で説明せよ。

課題 1.5

第 3回の課題のテーマについて考え、その構想について簡単なスケッチをしてみよ。現段階では実際にレイトレーシングで実行した結果を示す必要はない。

レポート提出方法について

各自ディレクトリを作成し、その下に kadai1 として (もしくは個別に kadai1.1, kadai1.2

などとしてもよい)どの課題かわかるようにした上で、プログラムファイル、実行結果、レポート一式を格納したものを tar で固めて提出すること。レポートは、できれば LATEXで作成し、pdf ファイル形式を電子メールで提出するのが望ましい。レポートが完成したら [email protected] に課題番号とレポート、そしてどのディレクトリにプログラムとその結果を保存したかを電子メールにて送信すること。もしファイルが大きすぎてメールサーバにはじかれた場合には、レポートの pdf ファイルのみを電子メールで提出することとし、そこに CED のアカウント名とレポートの問題を解いたディレクトリを記して下さい。ただしこの場合、自分以外の人がディレクトリを見れるよう、パーミッションを適切に設定すること (デフォルトでは見れるようになっているはずです)。第一回課題の提出締め切りは 11月 9日 (月)。なお、レポートの書き方が悪い学生には再提出を求める場合があるので、十分配慮して作成に臨むこと。

11

Page 16: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 4: 並列処理ってだいたいこんな感じ?

3 Hello MPI World!

並列処理とは何でしょうか? 上の図を実際の処理の様子と考えてイメージしてもらえると判りやすいかもしれません。並列処理とは複数の計算資源を同時に利用して単一の資源利用よりも効率的 (高速)に処理しようというものです。上の図では計算機資源としてネットワークで結合された複数の PC を例にしていますが、もし左下の利用者が右上の 5 台の PC を同時に使って計算できれば、端末 1 台よりも 5 倍の能力で計算できることになり処理時間も理論的には 1/5 になることが期待できます。なお、計算資源に PC を用いる他に、専用の計算機や専用の LSI などを用いて計算することもあります。並列計算のための計算機のことを並列計算機といい、スーパコンピュータと呼ばれる高価なものまで存在します。本実験では、専用計算機ではなくネットワーク接続された PC 端末を複数使って並列処理の実習をします。並列処理にはそれに用いるハードウェアに関連して様々な処理形態があります。ハードウェアで大きく分けると、処理をする複数のプロセッサで主記憶(メモリ)を共有するかしないかで分類されます。それぞれ、

• 共有メモリ型並列計算機

• 分散メモリ型並列計算機

と呼ばれています。これらの違いを図 5に示します。前者では全てのプロセスが同じメモリ空間をアクセスできるようにプログラミングできるため、メモリを中心に捉えて処理を担当するプロセスまたはスレッド (プロセッサに対応させて考えると良い)が複数いる状態が簡単に理解できます。図 5に示されるような複数のマシンで一つのメモリ空間を共有するシステムの代表例はマルチプロセッサのサーバシステムで、非常に高価であり一般に使われることは稀でしょう。しかし近年は複数のプロセッサやコアを積んだマシンも普及してきており、これらの場合には一台のマシンに搭載された複数のプロセッサやコアで一つのメモリ空間を共有して計算を行うことができます。一方後者の場合は個々のプロセッサにローカルメモリが装着され、各プロセッサはローカルメモリに対してのみアクセス可能なものです。しかし、並列処理を行う場合は他のプ

12

Page 17: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 5: 共有メモリと分散メモリの違いを理解できますか?

ロセッサがもつローカルメモリに格納された値を参照しなくてはならない場合が生じます。このような場合には、リモート (ローカルに対する対義語)メモリへのアクセスができない代わりに、一旦ネットワーク等を経由してリモートデータをローカルメモリにコピーしてからアクセスすることを行います。もちろん前者と後者を同時に利用することも可能で、最近の大型計算機はマルチプロセッサを搭載した多数の計算機を並列に利用できるように構成されています。この実験では、ネットワーク結合されたマルチコア搭載 PC 端末を、後者のシステムとして利用することになります。さて、この様な分散メモリ型並列計算機を利用する上で必要となるリモートデータをローカルメモリにコピーするなどの手続き一般を含む通信処理をメッセージパッシング(またはメッセージ通信)と呼びます。本実験で利用するメッセージパッシングのスタイルは、業界標準 (デファクトスタンダード)として定められている MPI (Message Passing

Interface)です。MPI そのものは通信関数の動作やその引数に関する決まりごとを定めた仕様書 (Specification)でしかありません。MPI を実際に並列計算機システム上で利用できるように実装したライブラリがいくつか存在します。本実験では MPICH2 version 1.5 rc3

を使用します。

13

Page 18: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

% make

mpicc -c -o ex1.o ex1.c

mpicc ex1.o -o ex1

% mpicc -show

cc -DUSE_STDARG -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -D

HAVE_STDARG_H=1 -DUSE_STDARG=1 -DMALLOC_RET_VOID=1 -L/usr/local/mpi/lib

-lmpich

図 6: MPI プログラムのコンパイル (画面の都合上適宜行末を折り返しています。)

3.1 Hello World を動かしてみよう

最初のプログラムは、ほとんどのプログラミング言語で行われるように “Hello World!”

から始めることにしましょう。MPI では複数のプロセスを扱うため、単純なメッセージの出力だけでなくメッセージの送受信を含めた変形版を用いることとします。

/home3/staff/ta000741/.ced_centos/exp2/ex1/

にソースファイル (ex1.c)とコンパイルに必要な Makefileを置いていますので、各自のディレクトリにコピーして make コマンドを実行してみてください。次の様にコンパイル・リンクが進行していくはずです。実行過程を見てわかるように、C ソースのコンパイルにはmpicc コマンドを用いてコンパイル・リンクを行います。mpicc は MPI をコンパイルするのに必要な環境変数やヘッダファイル、共有ライブラリの設定やパスなどを補う役割を担うシェルスクリプトです。コンパイルオプションなどの指定は cc コマンドとまったく変わりません。実際にどのような処理がなされるかは mpicc -show やコンパイル実行時に -v

オプションをつけて実行してみると分かります。さて、コンパイルに成功したファイル (ex1)の実行に移ります。並列処理を行わない場合は普通のコマンドのように、./ex1 とすることもできますが、まずは現在使用中の端末で複数のプロセスを使って処理してみましょう。次図の様にコマンドラインから入力していくと、オプション -np に続けて入力した数だけプロセスが生成されて、プロセスの数に応じてメッセージが表示されます。このように MPI プログラムの並列実行には mpirun コマンドを用いて、MPI 実行オブジェクトをその引数として各種パラメタを指定することで実現されます。ここまでの実行では、使用端末のみを用いるので厳密には並列処理とはいえず、並列処理を擬似しているに過ぎません。次に使用端末以外の端末資源を使って並列処理することを行ってみます。特に変わったことをしなくてもオプションを加えるだけで実現できます。

1. 準備として、使用する端末のリストを書き出したマシンファイル (hosts)を作成します (なお、次図 8の例では、現在使用中の端末に加えて他に 3 台の端末 (yellow01,

yellow02, yellow03)を利用する場合を想定しています)。マシンファイルの作成には、p.2 のリストを元に、実行端末が重ならないよう適当にシャッフルして各自用に作成したファイル hosts.<学籍番号> を

/home3/staff/ta000741/.ced_centos/exp2/hostfiles

14

Page 19: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

% mpirun -np 2 ./ex1

Hello! greeting from process 1.

% mpirun -np 3 ./ex1

Hello! greeting from process 1.

Hello! greeting from process 2.

% mpirun -np 1 ./ex1

The number of processes must be larger than 1.

[0] MPI Abort by user Aborting program !

[0] Aborting program!

p0_2136: p4_error: : 1

図 7: MPI プログラムの実行(その 1)'

&

$

%

% cat hosts

yellow01

yellow02

yellow03

% mpirun -machinefile hosts -np 4 ./ex1

Hello! greeting from process 1.

Hello! greeting from process 2.

Hello! greeting from process 3.

図 8: MPI プログラムの実行(その 2)

ディレクトリに置いたので、これを使うとよいでしょう。各自自分のファイルをコピーし、先頭の行に VNC 接続したマシンを加えて下さい。

2. 次に, mpirun コマンドに対してこのマシンファイルを -machinefile のオプションとして指定します。これで、マシンファイルに指定された端末でプロセスが実行され、本当の意味での並列処理が成されます。

図 8に実行結果を示していますが、これでは本当にマシンファイルに指定した端末を利用したのかが不明確です。次節でプログラムの解説を行いますので、それから本当にリモートの端末を利用したのかを確認してみましょう。

3.2 MPI プログラムの書き方の初歩の初歩

MPI のプログラムの書き方にはいくつかルールがあります。

1. ヘッダファイル mpi.h を取り込まなくてはならない。MPI では関数のほかに数多くの構造体や定数を利用します。したがって、mpi.hを取り込まないとコンパイルすることができない。

15

Page 20: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 9: メッセージパッシングのイメージ

2. できるだけ早い段階で, 関数 MPI_Init を呼び出して MPI の環境を初期化する必要がある。MPI_Init を呼び出す前に MPI の関数を利用することはできません。なお、MPI_Init の引数には関数main()の引数である, argc, argv のポインタを渡さなくてはならないので注意が必要です。

3. MPI プログラムの終了は 関数 MPI_Finalize を呼び出します。この関数呼び出し以降は MPI 関数を利用することはできません。

図 10は ex1.c のリストです。上の 1 から 3 の項目に対応する部分が分かるでしょうか?

3.2.1 プロセスのランク

次に、並列処理をする上で重要な項目「ランク」について説明します。並列処理を行う場合、ある特定のプロセスから見てそれ以外のプロセスが誰であるのかを一意に決めておかないとプロセス間で正しくデータをやり取りすることができません。これは現実の社会に当てはめると、各個人には名前がついていて、その名前があることで個人を識別できることに対応します。MPI で並列処理する場合、グループに属するプロセスには 0 から始まる番号が割り振られます。これをランクと呼びます。ランクはプロセスごとに異なっていて、ランクとプロセスが一対一に対応するようになっています。自分自身のランクを知る関数が MPI_Comm_rank です。関数の第一引数には、プロセスの通信を管理するコミュニケータを渡すことになっています。本実験では MPI_COMM_WORLD という全プロセスの通信を管理するコミュニケータを指定します。また、全プロセスの個数を知るための関数は MPI_Comm_sizeです。使用方法は MPI_Comm_

rank と同様です。これらの情報を用いることで、プロセスの個数で処理するデータを分割したり、特定ランクのプロセスに対して特別な役割を任せたりするプログラムを書くことができます。

3.2.2 通信 Send/Recv

MPI の中心的な役割は、任意のプロセス間でのメッセージのやり取りにあります。その役割を実現する基本関数は MPI_Send, MPI_Recv の 2 つです。これら関数は, 電子メールの仕組みに当てはめたときにメールの送り手 (Sender)が、メール送信ソフト (MPI_Send)

16

Page 21: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 10: Hello World! の MPI 版 (プログラム名: ex1)

17

Page 22: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

int MPI_Send(void *buf, int count, MPI_Datatype datatype,

int dest, int tag, MPI_Comm comm);

[IN buf] 送信バッファの開始アドレス (ポインタ)

[IN count] 送信バッファの要素数 (非負の整数)

[IN datatype] 送信バッファの個々の要素のデータ型 (ハンドル)

[IN dest] 送信先のランク (整数)

[IN tag] メッセージタグ (整数)

[IN comm] コミュニケータ (ハンドル)

int MPI_Recv(void *buf, int count, MPI_Datatype datatype,

int source, int tag, MPI_Comm comm,

MPI_Status *status);

[OUT buf] 受信バッファの開始アドレス (ポインタ)

[IN count] 受信バッファの要素数 (整数, 実際に送信されるメッセージの要素数と異なっ

ていてもよい)

[IN datatype] 受信バッファの個々の要素のデータ型 (ハンドル)

[IN source] 送り元のランク (整数)

[IN tag] メッセージタグ (整数)

[IN comm] コミュニケータ (ハンドル)

[OUT status] 状態を返すオブジェクト (Status構造体)

図 11: 関数 MPI Send/MPI Recvの仕様

を使ってメールを送信し、受け手 (Receiver)が POP などのメール受信ソフト (MPI_Recv)

を用いてメールを自分の端末に受信することに相当します。メールの送受信には From(Sender)/To(Receiver) を指定するように、MPI での送受信にもそれに呼応してランクを用いて送受信相手を指定します。また、メールには Subject を付けてその種別を知らせることができますが、MPI でもそれに対応したタグ (荷札)を付けられるようになっています。また、その他に送受信するメッセージ (データといった方が適当かもしれません)の型 (文字列, 整数, 浮動小数点数など)とその要素数を指定します。関数の引数は省略ができないので、数が多いですが毎回全て指定します。MPI_Send/MPI_Recv 関数の引数は図 11にある順に全て指定してください。送受信バッファに格納できる主なデータ型には表 12(左)に示すものがあります。メッセージの受け側では、ワイルドカードを指定することで到着順に受け取ることができます。また更に、実際に受け取ったメッセージの差出人、その荷札について情報を取得することができます。ワイルドカードと合わせてその使い方を表 12(右)に示しておきます。

18

Page 23: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

MPIデータ型 Cデータ型MPI_CHAR signed char

MPI_INT singed int

MPI_LONG signed long

MPI_UNSINGNED unsigned int

MPI_FLOAT float

MPI_DOUBLE double

MPI_BYTE

MPI_PACKED

差出人 (Sender)を特定しない場合:

sourceに MPI_ANY_SOURCEを指定メッセージの荷札 (タグ)を特定しない場合:

tagに MPI_ANY_TAGを指定実際の差出人を調べる場合:

status.MPI_SOURCE

(MPI_Status*)status->MPI_SOURCE

実際に受け取った荷札を調べる場合:

status.MPI_TAG

(MPI_Status*)status->MPI_TAG

図 12: 主な定義済み MPI データ型 (左)、ワイルドカードと MPI Statusの使い方 (右)

3.3 集団通信

前章では MPI での基本的な通信形態である Send/Recv を行いました。1 プロセスと 1

プロセスとの間でなされる通信であるため、これを一般的に 1 対 1 通信と呼びます。これに対して、特定の 1 プロセスと他の全プロセス、またはその逆である全プロセスから特定の 1 プロセスに向けた通信が存在します。

3.3.1 ブロードキャスト (Broadcast)

特定の 1 プロセス (ルートと呼ぶ)が保有するデータを、他の全プロセスに配布することをブロードキャストといいます。ブロードキャストの結果、全プロセスはルートの持っていたデータと全く同じデータを保持します。MPI_Bcast 関数でその機能を実現します。使い方の例として、ファイル入力 (もしくは標準入力)などでランク 0 プロセスのみが

fscanf 関数を実行し、それ以外のプロセスはランク 0 がブロードキャストした結果を用いるなどの利用方法があります。積分プログラム ex2 の場合は積分区間や分割個数の送信に使うことができます。

図 13: ブロードキャストの考え方

19

Page 24: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 14: MPI Bcast の使用例

❛�✁✂✄❛�❬✂✄❛�✱✂❪

❛�✁✂

❛�❬✂ ❛�✱✂

❛�☎✂

❛�✆✂

図 15: スキャッタの考え方

3.3.2 スキャッタ (Scatter)

ブロードキャストは全てのプロセスでまったく同じデータの複製を持つことを実現しますが、配列データの特定部分を受信する必要が生じる場合があります(例えば各プロセスのランクに相当する部分のデータのみをルートプロセスから受信するなど)。この様な集団通信をスキャッタと呼び、MPI_Scatter 関数がその機能を支援します。

3.3.3 ギャザー (Gather)

スキャッタのまったく逆の働きをするのが、ギャザーです。各プロセスが持つデータを特定プロセスに集約してランクに応じて配列要素に格納していく操作です。各プロセスが独立した計算を行い、最後にルートプロセスがその結果を集約し、統計処理するときなどに用いることがあります。関数 MPI_Gather を用います。

20

Page 25: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

• MPI_SUM 総和計算 • MPI_LAND 論理積 • MPI_BAND ビット積• MPI_MAX 最大値計算 • MPI_LOR 論理和 • MPI_BOR ビット和• MPI_MIN 最小値計算 • MPI_LXOR 排他論理和 • MPI_BXOR ビット排他和

図 16: MPI Opハンドルの種類と機能

3.3.4 リデュース (Reduce)

リデュース (MPI_Reduce)はギャザーで集約した配列データを基に、更に何らかの算術演算を行い結果を返すものです。例えば、各プロセスが計算した結果の総和をとったり、最大、最小を求めたりすることができます。また、論理演算など多くの演算が前もって定義されていますが、利用者が定義して登録することもできます。

4 CGプログラムの並列化指針

4.1 逐次版レイトレーシングプログラム

本実験で取り扱う、CG (レイトレーシング)プログラムの逐次版 (3種類)のソースファイル一式を次のディレクトリに置いています。

/home3/staff/ta000741/.ced_centos/exp2/serial1/ (OpenGLなし)

/home3/staff/ta000741/.ced_centos/exp2/serial2/ (OpenGLあり)

/home3/staff/ta000741/.ced_centos/exp2/serial3/ (OpenGLあり、逐次描画)

プログラムの内容を詳しく見ていくと分かると思いますが、これらプログラムは、serial1,

serial2, serial3 に行くに従って複雑になっています。したがって、その順に並列化が困難になります。

4.2 ファイル単位の単純な並列化

さて、上で紹介した serial1 プログラムを次のように実行すると、定義ファイル (*.cod)

を順次処理する仕様になっています。1 つ 1 つの定義ファイルの処理、つまり画像作成は、それぞれ独立な事象なので並列処理可能です。それぞれの定義ファイルについて、各端末上で ./rt2 ... として複数同時に処理することができますが、この実験では MPI を使って並列に処理することを考えていきましょう。まず、serial1 の中で引数以下の定義ファイルを順次処理する部分を探すと、関数 main

(glview.c)の中の for(filename_ptr=... のループ構造が相当することが分かります。従って、MPIによる並列化に必要な手続き (3.2章を参考に)を行った後で、各プロセスがそれぞれ担当する定義ファイルのみを利用するように for ループを改良するればよいことになります。for ループの部分を次の様に変更し, 変数 my_rank や world_size を先の ex1 を参考に修正すれば、ランク j のプロセスは j, j+world_size, j+2world_size, ... 番目に指定された定義ファイルを処理するようになります (課題 2.3)。

21

Page 26: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype,

int root, MPI_Comm comm );

[INOUT buffer] バッファの開始アドレス (ポインタ)

[IN count] バッファの要素数 (整数)

[IN datatype] バッファのデータ型 (ハンドル)

[IN root] ルートのランク (整数)

[IN comm] コミュニケータ (ハンドル)

int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,

void *recvbuf, int recvcount, MPI_Datatype recvtype,

int root, MPI_Comm comm);

[IN sendbuf] 送信バッファの開始アドレス (ポインタ)

[IN sendcount] 送信バッファの要素数 (整数)

[IN sendtype] 送信バッファのデータ型 (ハンドル)

[OUT recvbuf] 受信バッファの開始アドレス (ポインタ, ルートでのみ有効)

[IN recvcount] 1回の通信の要素数 (整数, ルートのみ有効)

[IN recvtype] 受信バッファ要素のデータ型 (ハンドル, ルートでのみ有効)

[IN root] 受信プロセスのランク (integer)

[IN comm] コミュニケータ (ハンドル)

int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,

void *recvbuf, int recvcount, MPI_Datatype recvtype,

int root, MPI_Comm comm);

[IN sendbuf] 送信バッファのアドレス (ポインタ, ルートでのみ有効)

[IN sendcount] 個々のプロセスに送信される要素の個数 (整数, ルートでのみ有効)

[IN sendtype] 送信バッファのデータ型 (ハンドル, ルートでのみ有効)

[OUT recvbuf] 受信バッファの開始アドレス (ポインタ)

[IN recvcount] 受信バッファの要素数 (整数)

[IN recvtype] 受信バッファ要素のデータ型 (ハンドル)

[IN root] 送信プロセスのランク (整数)

[IN comm] コミュニケータ (ハンドル)

int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,

MPI_Op op, int root, MPI_Comm comm);

[IN sendbuf] 送信バッファのアドレス (ポインタ)

[OUT recvbuf] 受信バッファのアドレス (ポインタ, ルートでのみ有効)

[IN count] 送信バッファの要素数 (整数)

[IN datatype] 送信バッファのデータ型 (ハンドル)

[IN op] 簡約操作 (ハンドル, MPI_SUM, MPI_MAX, MPI_MIN など)

[IN root] ルートのランク (整数)

[IN comm] コミュニケータ (ハンドル)

図 17: 代表的な集団通信関数の仕様

22

Page 27: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

% ./rt2 -p kotori bell airplane shrine woods wooden winter

図 18: 画素単位の並列処理の考え方

for(filename_ptr=my_rank; filename_ptr<num_files; filename_ptr+=world_size) {

...

}

4.3 マスター・スレーブ方式

先に示した定義ファイル単位の並列処理を実際に行うと、それほど効率がいいとはいえないことがすぐにわかります。その理由は、定義ファイルごとに処理に要する時間がかなり違うためです。例えば、kotori.cod と winter.cod では 20 倍以上違います。そうなると、この 2つの定義ファイルを 2プロセスで並列処理しても winter.cod の処理が圧倒的に多くなり、実際には 20/21 倍程度の速度向上しか望めなくなります。この問題は、各プロセスの処理時間を大体均等にすることで改善できますが、先に述べたように定義ファイルの処理時間はファイルによってかなりちがうこととその時間は予測ができないという難しさがあります。したがって、ファイル単位での並列化ではおのずと限界が来ることが予想できます。これを改善するために、1 つの定義ファイルの処理を複数プロセスで並列処理することを考えていきます。レイトレーシングの原理は基本的に画素単位の光線の追跡にあるので、画像を分割して部分ごとに並列処理することができます。図 18 に、kotori.cod を 4 プロセスで処理するために画像を 4 分割して各プロセスに割り付ける様子を示しました。ここで、一つ問題となることがあります。レイトレーシングは最終的に一つの画像として結果を取りまとめなくてはならないのに、このままでは分割したのみでバラバラな部分的な画像が存在するのみになってしまいます。そこで、部分的

23

Page 28: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

に生成された画像を集約して一枚の画像に完成させる特別な役割を果たすプロセスを決めて、そのプロセスに全体の制御を任せることにします。この特別な役割を担うプロセスをマスター (もしくはマネージャー)と呼び、それ以外のプロセスをスレーブ (もしくはワーカー)と呼ぶこととします。図 19 は、マスター・スレーブ方式で絵を描く場合の大まかな制御の流れを示しています。図からもわかるように、マスターはスレーブの仕事を取りまとめるだけなので、本来の処理以外に 1 プロセスを使うことになります。心情的には 1 プロセス(プロセッサ)を無駄にした気にさせられますが、マスタープロセスの重要性は後々わかってくるでしょう。このマスター・スレーブ方式には、マスターの数、スレーブへの仕事の割り当て方やそのタイミング、結果の収集の単位やそのタイミングなどに様々なバリエーションが考えられます。本実験では CG プログラムに適した手法として 2 種類を選択し、以下その実装方法について考察していきます。

図 19: マスター・スレーブ形態の処理方式

4.3.1 仕事の分割と割当て (静的な割当て方式)

serial1 を解析していくと、画素単位の処理は rt2.c 内の関数 DistributedRayTrace で行われていることがわかります。更に、DistributedRayTrace が呼ばれる部分は para.c

の関数 getImage_serial 内の次の 2 重ループ内です。

for (iy = my_SY0; iy>=my_SY1; iy--) {

for (ix = my_SX0; ix<=my_SX1; ix++) {

double r, g, b;

DistributedRayTrace (ix, iy, &r, &g, &b); /*{拡張} */

x = ix + S;

y = iy + S;

n = y*(2*S)+x;

image[3*n+0]=(unsigned char) (r * 255.0);

image[3*n+1]=(unsigned char) (g * 255.0);

image[3*n+2]=(unsigned char) (b * 255.0);

}

}

このループは (my_SX0,my_SY0)-(my_SX1,my_SY1) の部分矩形領域 (ブロック)を描画しています。全画像の (-S,-S)-(S-1,S-1) の 2S × 2S のドットをブロックを基本単位と

24

Page 29: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

して分割し、分割したブロックを順番にループで回して処理をしています。上に示した for

ループの直前の while ループがブロック単位の逐次処理を制御しています。全領域のブロックへの分割は関数 InitDrawArea が行っており、配列 area_list_x[],

area_list_y[]を参照することで、ブロックの隅の座標を得られます。ブロックのサイズは一定 (CHUNK_X×CHUNK_Y)ですので、ブロック内の座標において逐次レイトレーシングを実行することができます。総ブロック数は ((2*draw S)/CHUNK X+1)*((2*draw S) /CHUNK Y+1)

になります。この分割のもとで、描画をマスター・スレーブ方式で行うことを考えると、まず、各スレーブプロセスはそれをスレーブの数 (world_size-1)で均等に分割した個数のブロック情報をマスターから受け取り、次に、担当するブロックのレイトレーシングを行います。最終的に結果をマスターに返すことになります。この様に、処理を開始する前に処理すべき担当ブロックを分割し、スレーブに割り当ててしまうやり方を、それぞれ静的な分割、静的な割当てと呼びます。この方法をもとに並列化をしたプログラムを次のディレクトリにおいています (ただし、関数等の記述が抜けているため、このままでは動作しません。課題 2.4)。

/home3/staff/ta000741/.ced_centos/exp2/ex3/

ブロック図 20の様に、各スレーブはブロック内に含まれるドットのレイトレーシングをしたのち結果 (部分画像)をマスターに送信します。マスターとスレーブでは動作がかなり異なります。そこで、マスターは getImage_manager, スレーブは getImage_worker で処理するように分けてプログラムを作成しています。また、プログラム ex3 の para.c からも分かるように、スレーブは部分画像のビットマップ情報と全体の画像のどの部分かという情報を併せて送ります。また、各メッセージのタグに継続: CG_CONT (まだ処理すべきブロックが存在する)もしくは終了: CG_END を指定します。マスタープロセスは受信したビットマップ情報を取りまとめ一つの画像にします。更に、終了信号を数え上げて総数がスレーブの数になれば、次の画像に移ることにします。

図 20: 静的分割・静的割当て方式におけるマスター・スレーブ間のデータ送受信 (スレーブが 1 プロセスの場合)

25

Page 30: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

4.3.2 仕事の割当て (タスクプール方式)

静的な分割・割当て方式では画像を単純に等分されたブロックをあらかじめ決まったプロセスに割り当ててしまうために、ある部分領域に処理に時間がかかる場合、それを担当するスレーブプロセスの処理時間が全体の処理を支配してしまうことがあります。他のプロセスはすでに処理を終了し、遊んでいる (アイドル)状態にあります。最後まで処理が終わらないプロセスの仕事を分担させることも可能であり、もしそれができれば全体の処理は早く終わらせられることになります。スレーブプロセスは自分に割り当てられたブロックの処理に専念しているため、他のプロセスの状況は知ることができません (つまり自分は早く処理を終らせたのか、他よりも遅いのか知る術がありません)から、処理が遅いからといって未処理のブロックを他のスレーブにプロセスに割り振るわけにも行きません。もともと全体の仕事の統括はマスタープロセスの仕事ですから、マスタープロセスが早く処理を終わらせたスレーブプロセスに仕事を再度割り振るようにすべきです。そこで、次の様に仕事の割り振り方を変更します(概略のみ。実際のプログラムではかなり違うので注意すること)。'

&

$

%

1. 処理単位であるブロックに仕事を細かく分けます。そして細かく分けたブロックの総数をNとします。

2. P個のスレーブプロセスに仕事を分けますが、一度にN/P ブロックずつではなく nブロックずつ割り振ることにします。ここで、nP ≪ N とします。

3. 各スレーブプロセスは割り当てられたブロックを処理し、結果をマスターに返します。

4. スレーブ内で処理すべきブロックが無くなったら、マスターに次の仕事を要求します。

5. マスターは、未処理のブロックがあればスレーブの要求に答えて nブロックを再度割り振ります。

6. 仕事が割り振られなかったスレーブは、マスターに終了信号を送ります。

7. マスターは、全スレーブプロセスから終了信号を受け取るまで処理を継続します。

以上の手続きで、処理中にマスターが仕事 (未処理のブロック)を管理し効率的にスレーブに割り振ることができるようになります。この手法を動的な割当て方式といい、マスターが保持する仕事のリスト(タスクをプールしたもの)からスレーブが仕事をもらっていくということでタスクプール方式とも呼ばれます。この手法におけるマスター・スレーブ間のメッセージの送受信の様子を表した図が図 21になります。

26

Page 31: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 21: タスクプール方式におけるマスター・スレーブ間のデータ送受信 (スレーブが 1 プロセスの場合)

5 CG 並列処理での通信の効率化

5.1 仕事の分割 (タスクプール方式)の続き

プログラム ex3 を具体的に修正すべき点は、次に挙げる 3 点です。

1. 仕事 (ブロック)を分割し分配する関数 SendDrawArea(rank) で、1 回の呼び出しでリストから CHUNK_B 個ずつ取り出し指定されたプロセスに送るように変更。また、メッセージを送る際に、実際に有効なブロック数 (num_p)をタグに指定する。

2. スレーブは受信するブロックリスト数を CHUNK_B に固定し、制御構造を次の様に変更する

buff = malloc(sizeof(int)*4*CHUNK_B);

while ( 1 ) { // 新たに追加MPI_Recv(buff,4*CHUNK_B,MPI_INT,

0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);

num_p = status.MPI_TAG;

if ( num_p <= 0 ) break;

for(i=0;i<num_p;i++) {

... 各ブロック単位のレイトレーシング処理 ...

MPI_Send(buffRGB,sizeof(struct message_t),MPI_BYTE,

0,CG_CONT,MPI_COMM_WORLD); // 1ブロック分結果送信}

MPI_Send(buffRGB,0,MPI_BYTE,

0,CG_NEXT,MPI_COMM_WORLD); // 次のブロックを要求}

MPI_Send(buffRGB,0,MPI_BYTE,

0,CG_END,MPI_COMM_WORLD); // 終了信号送信free(buff);

27

Page 32: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

3. マスターはスレーブからタグに CG_NEXT が送られてきたときに、再度ブロックリストを送信するために次の様にタグに応じた switch 文を修正する。

MPI_Recv(buffRGB,sizeof(struct message_t),MPI_BYTE,

MPI_ANY_SOURCE, MPI_ANY_TAG,

MPI_COMM_WORLD, &status);

rank = status.MPI_SOURCE;

tag = status.MPI_TAG;

switch ( tag ) {

case CG_CONT:

break;

case CG_NEXT:

SendDrawArea(rank);

continue;

case CG_END:

done_processes++;

continue;

}

5.2 データ送受信と計算のオーバーラップ

これまでに説明した MPI の通信関数は、通信関数内で通信動作が完了するまでプログラムに制御を返さないというものでした。この様に、通信動作の間中プログラムの進行を止めてしまう通信関数をブロッキング通信関数と呼びます。これに対して、通信動作に必要なパラメータを通信機構 (MPIが管理するため利用者は特に意識する必要は無い)に渡した後に直ちにプログラム本体に戻ってくるというものがあります。この様な通信形態をノンブロッキング通信と呼び、この実験で使用する関数は図22に挙げるようなものです。ノンブロッキング通信では通信動作そのものは通信機構に委ねられるために、制御がプログラムに戻ってきた後は通常のプログラムを実行することができます。プログラムの実行の裏側で通信がなされるために、通信と計算をオーバーラップさせることができ、通信待ちなどのオーバーヘッドを削減できる可能性があります。1

ノンブロッキング通信関数の使い方は、MPI_Send や MPI_Recv と同じように通信を開始したい位置で MPI_Isend や MPI_Irecv を呼び出します。ただし、この 2 つの関数は通信の開始を指示するだけなので、通信そのものが完了したどうかを知ることができません。そのため、送信バッファの内容を更新したり、受信バッファの内容を参照することがいつまでもできません。通信完了を確認する関数 MPI_Wait を使います。

5.3 ダブルバッファ

マスター側の処理はスレーブからデータを受け取ってから処理を進行する仕組みとなっていますが、ノンブロッキング通信を使ってこれを実現する場合には (1) 受信に利用されるバッファと (2) 通信が完了し実際の処理に利用されるバッファの 2 種類を用いる必要があります。2 種類のバッファを buffA, buffB と名前をつけた時に、「buffA を (1)に buffB

を (2)にする ‘ケース I’」と「buffA を (2)に buffB を (1)にする ‘ケース II’」を切り替え

1ただし、通信機構の実現はハードウェアや OS などによって異なるため、一般的には実装依存となります。一概にオーバーラップといっても論理的にその様に動作するだけに過ぎない場合もあります。

28

Page 33: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dest,

int tag, MPI_Comm comm, MPI_Request *request);

[IN buf] 送信バッファの開始アドレス (ポインタ)

[IN count] 送信バッファの要素数 (非負の整数)

[IN datatype] 送信バッファの個々の要素のデータ型 (ハンドル)

[IN dest] 送信先のランク (整数)

[IN tag] メッセージタグ (整数)

[IN comm] コミュニケータ (ハンドル)

[OUT request] 通信リクエスト (ハンドル)

int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source,

int tag, MPI_Comm comm, MPI_Request *request);

[OUT buf] 受信バッファの開始アドレス (ポインタ)

[IN count] 受信バッファの要素数 (整数)

[IN datatype] 受信バッファの個々の要素のデータ型 (ハンドル)

[IN source] 送り元のランク (整数)

[IN tag] メッセージタグ (整数)

[IN comm] コミュニケータ (ハンドル)

[OUT request] 通信リクエスト (ハンドル)

int MPI_Wait(MPI_Request *request, MPI_Status *status);

[INOUT request] リクエスト (ハンドル)

[OUT status] 状態を返すオブジェクト (Status構造体)

int MPI_Cancel(MPI_Request *request);

[IN request] 通信リクエスト (ハンドル)

図 22: ノンブロッキング通信関数の仕様

29

Page 34: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 23: ノンブロッキング通信の使用例

ながら繰り返すことになります。通常、この 2 ケースに対応する 2 つのコードを書くことになりますが、2 重化されたバッファーをポインタ配列などで管理し、ケース I と II の切り替え時にポインタ配列のアドレスを切り替えれば、プログラム自体を 1 本化することができます。この方式をダブルバッファ方式といいます。この一連の処理の骨格をプログラミングしたものが次のリストになります。

// 変数 swによって現在使用するバッファを指定するsw = 0;

MPI_Irecv(buffRGBs[sw], ... MPI_COMM_WORLD, &req[sw]);

while ( 1 ) {

if ( ... ) break;

// 次のメッセージ受信リクエストを発行するMPI_Irecv(buffRGBs[1-sw], ... MPI_COMM_WORLD, &req[1-sw]);

// 現在の通信リクエストの終了を待つMPI_Wait(&req[sw],&status);

// バッファを切り替えるsw = 1-sw;

.....

}

// 既に発行済みの通信リクエストをキャンセルするMPI_Cancel(&req[sw]);

30

Page 35: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

5.4 第二回課題

課題 2.1

プログラム ex1 はどういう動作をしているか、各自実際に動作させるとともに、図 7の結果等を考慮して説明せよ。

課題 2.2

ランク 0 が読み込んだファイルの情報を、ランク 1, 2, 3, ... とリレーし最後再びランク 0

に戻すプログラムを作成せよ。そして、正しく情報がリレーされたことを確認せよ。

課題 2.3

プログラム serial1 を定義ファイル単位で並列処理するように改良し、実際にサンプルファイルを用いて並列に実行せよ。

課題 2.4

プログラム ex3 を完成させよ。また、ワーカのプロセス数を 1, 2, 4, 8, 16 と増やして並列処理すれば処理時間が減少することを確認せよ (-np オプション +1 に注意!)。注意: -machinefile で適切にオプションを指定することと、他のユーザが計算していないことを確認して並列処理すること。

課題 2.5

プログラム ex3 をタスクプール方式で並列化し、静的分割版とタスクプール方式版との実行結果を次の条件で比較せよ。

• サンプルファイル: winter.ray を使用し、

• スレーブのプロセス数を 1, 2, 4, 8, 16 と変化させる。

注意: -machinefile で適切にオプションを指定することと、他のユーザが計算していないことを確認して並列処理すること。

レポート提出方法について

各自ディレクトリを作成し、その下に kadai2 など (個別に kadai2.1, kadai2.2 などでもよい)どの課題かわかるようにし、プログラムファイル、実行結果、レポート一式を格納したものを tarで固めて提出すること。レポートは、できれば LATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。レポートが完成したら [email protected] に課題番号とレポート、そしてどのディレクトリにプログラムとその結果を保存したかを電子メールにて送信すること。

31

Page 36: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

もしファイルが大きすぎてメールサーバにはじかれた場合には、レポートの pdf ファイルのみを電子メールで提出することとし、そこに CED のアカウント名とレポートの問題を解いたディレクトリを記して下さい。ただしこの場合、自分以外の人がディレクトリを見れるよう、パーミッションを適切に設定すること (デフォルトでは見れるようになっているはずです)。第二回課題の提出締め切りは 11月 18日 (水)。なお、レポートの書き方が悪い学生には再提出を求める場合があるので、十分配慮して作成に臨むこと。

32

Page 37: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

6 CG 最終課題

6.1 第三回課題

課題 3.1

レイトレーシングのサンプルと付録につけたデータ定義ファイルの書き方を参考にして、次のうちから各自好きな 1 テーマをモチーフにして、実験で完成させた並列レイトレーシングを用いて絵を作成すること。

1. 動物・ペット

2. 歴史的な建造物

3. 乗り物

4. 歴史的人物や自画像

5. 絵画のデフォルメ

6. その他

課題 3.2

本実験ラウンドの感想を書け。

自由課題

上の課題でも物足りない学生は、付録 C を参考に OpenGL 対応の並列レイトレーシングプログラムを作成すること。なお、この課題は単位認定とは関係が無いので、興味が無い学生は行わなくてもよい。

レポート提出方法について

各自ディレクトリを作成し、その下に kadai3 (もしくは個別に kadai3.1, kadai3.2 などでもよい)、どの課題かわかるようにし、プログラムファイル、実行結果、レポート一式を格納したものを tar で固めて提出すること。レポートは、できれば LATEXで作成し、pdf

ファイル形式を電子メールで提出することが望ましい。もしファイルが大きすぎてメールサーバにはじかれた場合には、レポートの pdf ファイルのみを電子メールで提出することとし、そこに CED のアカウント名とレポートの問題を解いたディレクトリを記して下さい。第三回課題の提出締め切りは 12月 16日 (水)。なお、最終回につきレポートの再提出は認めないので、十分配慮して作成に臨むこと。

33

Page 38: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

A (付録)レイトレーシングデータの記述について参考書のレイトレーシングプログラムで用いているデータ記述は、次の 5 つの定義に分かれています。

視野の定義照明環境の定義物体の属性の定義物体の構造の定義画像生成の対象となる物体の定義

以下の説明で、太字の部分はキーワード (予約語)としてそのまま書く部分です。

A.1 視野の定義

視点とスクリーンの配置を行う。#

"

!

view

eye vx vy vztarget tx ty tzscreen S ϕ γ

eye

(vx, vy, vz) 視点の座標target

(tx, ty, tz) 目標の座標(スクリーンの中心を決める)screen

S スクリーンのサイズ (幅の半分の値)

ϕ 画角 (度)

γ スクリーンの傾き (度)

A.2 照明環境の定義

物体が置かれている照明環境を定義する。'

&

$

%

light

back IbR IbG IbBamb Ca IaR IaG IaBpara Cp IpR IpG IpB Lx Ly Lz

point k Cq IqR IqG IqB xL yL zL

34

Page 39: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

back

(IbR, IbG, IbB) 背景色のRGB値 (0 · · · 1)amb

Ca 環境光の強さ (≥ 0)

(IaR, IaG, IaB) 環境光のRGB値 (0 · · · 1)para

Cp 平行光源の強さ (≥ 0)

(IpR, IpG, IpB) 平行光源のRGB値 (0 · · · 1)(Lx, Ly, Lz) 平行光源の光源ベクトル

point

k 点光源の減衰の種類0:減衰しない1:距離に比例して減衰2:距離の 2乗に比例して減衰

Cq 点光源の強さ (≥ 0)

(IqR, IqG, IqB) 点光源のRGB値 (0 · · · 1)(xL, yL, zL) 点光源の座標

A.3 物体の属性の定義

物体の色や材質の定義を行う。定義した属性は基本立体に対しても、いくつか組み合わせた後の部品に対しても利用することができる。#

"

!

attribute

属性の定義属性の定義...

属性の定義:

属性名kd kdR kdG kdBks ksR ksG ksBtrace

hl m

cn n

ct ctR ctG ctB

35

Page 40: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

kd

(kdR, kdG, kdB) 拡散反射係数 (0 · · · 1)ks

(ksR, ksG, ksB) 鏡面物体の鏡面反射係数 (0 · · · 1)trace 写り込みがある場合に指定hl

m ハイライトの広がりを表す定数(鏡面反射をハイライトで近似する場合は 1以上の整数)

cn

n 屈折率 (· · · 1 · · · )ct

(ctR, ctG, ctB) 透過調整用係数 (0 · · · 1)

A.4 物体の構造の定義

物体の構造の定義を行う。構造名は再利用することができるが、再定義すると上書きされるので注意が必要。#

"

!

structure

構造名=構造の定義式構造名=属性の定義式...

構造の定義式:

因子 項 項 · · ·

因子:

基本立体定義構造名 (構造定義式)

基本立体定義:

plane a b c

ellip a b c

cone 軸 a b c

hyper1 軸 a b c

hyper2 軸 a b c

plane 平面 ax+ by + cz ≤ 0

ellip 楕円面 x2/a2 + y2/b2 + z2/c2 ≤ 1

cone 楕円錘面 x2/a2 − y2/b2 + z2/c2 ≤ 0 (軸が y 軸の場合)

hyper1 一葉双曲面 x2/a2 − y2/b2 + z2/c2 ≤ 1 (軸が y 軸の場合)

hyper2 二葉双曲面 x2/a2 − y2/b2 + z2/c2 ≤ −1 (軸が y 軸の場合)

軸は x, y, zで指定楕円面では値を 0 とすると ∞ としたのと同じ効果

36

Page 41: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

項:

集合演算の指定アフィン変換の指定属性の指定テクスチャマッピングの指定

集合演算の指定:

| 因子- 因子& 因子+ 因子

| 和− 差& 積+ アセンブル

アフィン変換の指定:

move tx ty tzmx txmy tymz tzrot α β γ

rx α

ry β

rz γ

scale l m n

sx l

sy m

sz n

shear α β γ ϵ δ ζ

shx α β

shy γ ϵ

shz δ ζ

move 平行移動mj j軸方向への平行移動rot 回転 (度)

rj j軸周りの回転 (度)

scale スケール変換 (軸方向への拡大・縮小)

sj j軸方向へのスケール変換shear 剪断shj j軸方向の剪断

属性の指定:

37

Page 42: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

att 属性名

テクスチャマッピングの指定:

cmap m Su Sv R1 G1 B1 R2 G2 B2

bmap m u0 v0 Wl Wd Wh

cmap 色マッピング (市松模様指定)

bmap バンプマッピング (波紋指定)

m マッピング対象種類(1: 平面, 2: 球体, 3: 円柱)

Su, Sv u, vそれぞれの方向のマッピングパターンの大きさ(角度を座標とする場合は、1周で繰り返すパターン数)

(R∗, G∗, B∗) 市松模様に使う色Wl 波の 1周期長Wd 振幅の減衰係数Wh 波紋の中心での波の振幅

A.5 画像生成の対象とする物体の定義

画像に置く物体の指定を行う (最後にピリオドを忘れずに書くこと)。�

�member 構造名 構造名 · · · .

A.6 「ことり」を例に簡単な説明

kotori.ray(図 24)を例にして説明します。ファイルは, view, light, attribute, structure,

memberの 5つで構成されており、それぞれで前節までで説明した内容の定義をしています。視点や光源、属性については資料を読みながら試行錯誤をしてください。その過程で理解できると思います。物体 (オブジェクト)の定義について説明します。物体は最終的にmemberの個所で指定されるものの他に、適時名前を付けた中間オブジェクトを定義することができます。それを、適宜使用することで見やすい rayファイルなります。kotori.rayの場合は 2羽の小鳥が枝にとまっているイメージです。小鳥の形状は同じで色だけ変えていますので、kotoriを定義してそれについて表面の色属性 (+位置も)を変えたaokotori, akakotoriを定義しています。枝や小鳥そのものは簡単なプリミティブを組み合わせて作っています。例えば枝は双曲面を 2つの平面で切り落として作っているだけです。もう少し工夫をしたければ、小枝をつけたり、幹の部分に模様をつけるために色属性を変えた球を組み合わせて(和をとる)実現することができるでしょう。また、小鳥はくちばしを円錐、頭を球にくちばしをつけたもの、胴体を楕円球として頭と胴体をくっつけて作っています。更に、細かな部品を作って足していくこと(引いてもよい)で、よりリアルなオブジェクトを定義できます。

38

Page 43: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

/* 図 2.31 データ記述/小鳥 */

view

eye 300 250 -75

target 0 150 100

screen 199 23.5 0

light amb 0.1 1 1 1

para 1 1 1 1 1 1 0

back 0 0.5 0.5

attribute

aka kd 1 0 0 ks 1 1 1 ct 0 0 0 hl 12 cn 1

ao kd 0 0 1 ks 1 1 1 ct 0 0 0 hl 12 cn 1

ki kd 1 1 0 ks 1 1 1 ct 0 0 0 hl 12 cn 1

midori kd 0 1 0 ks 1 1 1 ct 0 0 0 hl 12 cn 1

structure

kuchibashi = cone x 30 10 10 & (ellip 20 20 20 mx 20) att ki

atama = ellip 20 20 20 + (kuchibashi mx -40)

kotori = ellip 50 20 20 | (atama ry -20 rz 45 mx -50 my 30)

rz -20 ry -110 mx -100 my 55

aokotori = kotori att ao

akakotori = kotori att aka sx -1

dai = hyper1 x 60 20 20 & ellip 100 100 100 att midori

tsugai = aokotori + dai + akakotori ry -90 my 100 mz 100

member

tsugai.

図 24: kotori.ray

B (付録)レイトレーシングのモチーフデザインの仕方本実験で扱うレイトレーシングは 3 次元の物体を扱いそれを 2 次元のウィンドウに表示するため、デザインが容易ではありません。そこで、初めはいろいろなオブジェクトを 2

次元的に配置して見る角度を変えたり、オブジェクトを回転させたり配置を変えたりするといいでしょう。また、初めはライトなどには手を加えず背景光だけで絵を描きましょう。オブジェクトを透明にするのも初めのうちはやめておきましょう。さて、オブジェクトの数が増えるとレイトレーシングの実行時間がかかるので、ラフスケッチつまりまだデザインの段階でのレイトレーシングには、ドットを間引くオプション(-n)を指定して利用しましょう。このオプションを指定するとジャギー防止のためのアンチエイリアシングを行わないのと同時に 1 ドットおきにしか描画をしないので、通常の rt2 よりも 10 倍以上速く 1 枚の絵を描きます。もちろんその分絵の品質は落ちます。これをデザイン段階に使ってオブジェクトの配置を決めていくと効率が良くなります。ある程度出来上がったら並列処理をしていきましょう。

39

Page 44: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

これまでの実験で学生が作成した CG の作品を次のギャラリーに展示しています。参考にすると良いでしょう。

http://www.im.uec.ac.jp/~tatsuno/lectures/exp2/

C (付録) OpenGL との関連実験本編ではプログラム serial1 をもとに並列化を行ってきましたが、OpenGL によって結果を画面に描画する serial2 もしくは serial3 の並列化について補足します。

C.1 OpenGL を用いる上での問題点

OpenGL を用いて画面表示するには、OpenGL の描画モデルに即して描画のイベントや画面切り替えなどを行わなくてはならず、マスタープロセスの動作にわずかながらの修正が必要となります。図 25は OpenGL の動作の概要を示すものです。通常のプログラムと制御の方法が違って、OpenGL の MainLoop 関数を呼び出した後はグラフィックに関してその都度発生するイベントに応じたハンドラ関数を呼び出すことになります。つまり、プログラムの処理単位をイベントに分けて、それぞれのイベントに応じた関数をハンドラとして登録するというスタイルになります。

図 25: OpenGLの動作概要

OpenGL の MainLoop 関数を呼び出す前には各種の初期化関数と環境設定、ハンドラの登録等を行う必要があります。最後に glutMainLoop 関数を呼び出して、OpenGL からイベントごとに処理する状態に移行します。なお、動作原理から分かるようにそれ以降に記述された実行文などは基本的に意味を成しません。

40

Page 45: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

'

&

$

%

// OpenGLのユーティリティライブラリ (GLU)の初期化glutInit( &argc, argv );

glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );

// Windowの作成glutInitWindowSize(200,200);

glutInitWindowPosition(100, 100);

glutCreateWindow(argv[0]);

// 各種環境設定glClearColor( .0, .0, .0, .0 );

glShadeModel( GL_FLAT );

glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

// ハンドラ関数の登録などglutDisplayFunc(display);

glutIdleFunc(raytracer0);

glutReshapeFunc(reshape);

glutKeyboardFunc(NULL);

glutMainLoop();

これら一連の OpenGL の初期化やハンドルの定義等のパッチを

/home3/staff/ta000741/.ced_centos/exp2/patch/patch-glview

に置いています。glview にパッチを当てて再コンパイルしてみると、一枚の画像が描画し終わるとウィンドウに絵が表示されるようになります。パッチの当て方は�� ��% patch < patch-glview

C.1.1 計算途中の画像をディスプレイ表示するには?

では、画像を 1 枚表示し終わる前の途中段階で絵を見るにはどうしたらいいのでしょうか? これには少しプログラムに手を入れる必要があります。なぜなら、今ビットマップを作成して表示させるハンドラは glutIdleFunc() に登録されている raytracer0 もしくはraytracer1であり、その中からレイトレーシングの制御関数 getImageを呼んでそれが全て終了してから画面の更新 (関数 glutPostRedisplay()を呼び出して適当なタイミングで再描画イベントを登録している)を行っているからです。全ブロックの処理を終了してからではなく、数ブロックの処理を行ってから再描画イベントを送るという形にマスター側の制御を変更しなくてはなりません。そのためには、マスター側の関数 getImage_manager

を次のように変更します。

1. 変数 done を用意し、0 で初期化する。これは 1 画像が終了したかどうかを判別するフラグ変数として使う。1 画像の開始については変数 getImage_counter が 0 であれば描画開始と考える。

41

Page 46: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

2. 1画像の処理終了は全てのスレーブプロセスからの終了信号を受け取ったときなので、

if ( done_processes >= world_size-1 ) {

done = 1; // 1画像終了フラグを立てる処理break;

}

の様に修正する。

3. ループを途中で抜け出すようにwhile(1)のループの最後に

if ( (++getImage_counter)%VIEW_STEP==0 ) break; // VIEW_STEP 個のブロックを描画する毎にループを抜ける

を追加する。

4. ループを抜けた後で、次に getImage_manager を呼び出したときに、新たな画像処理開始を識別させるため変数 getImage_counter を 0 にする関数 getImage_init()を呼び出す処理と、次に呼び出すべきハンドラ関数を知らせるため返り値を次のように設定する。

if ( done ) {

FinDrawArea();

getImage_init();

free(buffRGB);

return 0; // 次のハンドラを raytracer0 にする} else {

return 1; // 次のハンドラを再度 raytracer1 にする}

D (付録) 立体視にチャレンジ

D.1 立体視画像の仕組み

ray ファイルは 3 次元立体のデータを保有しているので、うまく使ってやれば作品を立体視することもできます。左右 2つの眼を持った我々が物体を見ているのは、通常図 26(b)

のような仕組みです。これまでに本実験で行ってきた図 26(a)のスクリーンを、(b)にある2枚のスクリーンに置き換えることで立体視が実現できます。具体的には、ray ファイル内で記述した eye の位置を x 軸方向にずらすことによって、視点差のある 2枚の画像を作ればよいでしょう。これら左右にずらした画像をそれぞれ左眼用と右眼用とし、2つの画像を横に並べて VR ゴーグルで覗くと、平面画像が立体的に見えるはずです。

D.2 立体視画像の作り方

前節で説明した一通りの作業を行う 3Dgraphic.pl という perl スクリプトを用意しました。CED のディレクトリ

/home3/staff/ta000741/.ced_centos/exp2/3Dgraphic/

42

Page 47: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

(a) 通常の描画イメージ (b) 立体視画像の描画イメージ

図 26: レイトレーシングによる平面画像と立体視画像の描画方法の違い

においてあります。このファイルの使い方は、

1. rt1, rt2 が実行可能なディレクトリに立体視したい画像の ray ファイルを用意する。

2. 同じディレクトリに 3Dgraphic.pl をコピーする。

3. ターミナルから

./3Dgraphic.pl picture 20 または perl 3Dgraphic.pl picture 20

を実行する。第一引数には立体視したい画像のファイル名、第二引数には横方向にずらす距離を整数値で指定する。

4. 作成された picture3D.pngを手持ちのスマートフォンに保存し、横画面表示して VR

ゴーグルで覗く。

という流れです。ただし 3 で、rt1, rt2 同様に、3Dgraphic.pl を実行するとき第一引数に .ray はつけないことに注意して下さい。もし buffer overflow detected のエラーが出たときは、入力ファイル名が長すぎます。あとで説明するように、+, - などをつけても rt1,

rt2 が読み込めるよう、少し短い名前 (7文字以内)にしてください。作成された 3D 画像の例を図 27に示します。立体視がうまくできるのは、画面中心部の比較的眼に近い位置に物体があり、また奥行きがあるような画像です。kotori は鳥が左右にわかれているのであまり向きません。また距離によっても横方向にずらす距離を変える必要があるかもしれません。onigo3D.png (図 27)は研究室の 4年生が作成したものですが、立体感がうまく出ています。この図を作るために、前後にものを置いたり、数字を調整したり、色々と試行錯誤したそうです。3Dgraphic.plはスクリプトなので内部はテキストです。中を直接見たり編集したりすることができます。具体的には以下の手順で立体画像を作成しています。まず picture.ray

から左右に視点をずらした picture+.ray, picture-.ray という 2つの .ray ファイルを

43

Page 48: 「レイトレーシングの並列処理」tatsuno/lectures/exp2/mpi.pdfレポートはLATEXで作成し、pdf ファイル形式を電子メールで提出することが望ましい。電子メールによるレポート提出先はexp2report@googlegroups.com

図 27: 立体視画像の完成例

作成します。さらにこれらを rt1, rt2 にかけて、picture+.png, picture-.png という 2

つの png 画像を作成します。最後にこれらを ImageMagick の convert +append コマンドを使って左右に貼り付け、picture3D.png ファイルを作成します。このファイルが立体視用画像ファイル (図 27)です。

44