31
|
1 \chapter{並列プログラミングフレームワーク Cerium}
|
4
|
2 Cerium は、当初 Cell 用の Fine-Grain TaskManager として当研究室で開発された。
|
|
3 本章では Cerium の実装について説明する。
|
|
4
|
|
5 \section{Cerium の概要}
|
|
6 Cerium は当初 Cell 用であったが、現在では Linux、 MaxOS X上で動作する。
|
|
7 GPGPU の Data Parallel を含めて同じ形式で記述できる。
|
|
8
|
|
9 CeriumはTaskManager、 SceneGraph、Rendering Engine の3つの要素から構成される。
|
|
10 本研究では Cerium の TaskManager を汎用計算フレームワークとして改良を行う。
|
|
11 これによりヘテロジニアス環境に対応したシステムやフレームワークに必要な API や機構について考察していく。
|
|
12 \section{Cerium TaskManager}
|
|
13 Cerium TaskManager では、処理の単位を Task としてプログラムを記述していく。
|
|
14 関数やサブルーチンを Task として扱い、 Task 間の依存関係を考慮しながら実行される。
|
|
15 Task を生成する際に、以下のような要素を設定することができる。
|
|
16
|
|
17 \begin{itemize}
|
|
18 \item input data
|
|
19 \item output data
|
|
20 \item parameter
|
|
21 \item cpu type
|
|
22 \item dependency
|
|
23 \end{itemize}
|
|
24
|
|
25 input/output data, parameter は関数で言うところの引数に相当する。
|
|
26 cpu type は Task が動作する Device を示し、 dependency は他の Task との依存関係を表す。
|
|
27
|
|
28 \section{Cerium における Task}
|
|
29 図:\ref{fig:taskmanager}は Cerium が Task を生成/実行する場合のクラスの構成図である。
|
|
30 TaskManager で依存関係が解消され、実行可能になった Task は ActiveTaskList に移される。
|
|
31 ActiveTaskList に移された Task は依存関係が存在しないのでどのような順番で実行されても良い。
|
|
32 Task は転送を行いやすい TaskList に変換され、cpu type に対応した Scheduler に転送される。
|
|
33 なお、転送はSynchronozed Queue である mail を通して行われる。
|
0
|
34
|
|
35
|
4
|
36 \begin{figure}[htpb]
|
|
37 \begin{center}
|
|
38 \includegraphics[scale=0.7]{./images/createTask.pdf}
|
|
39 \end{center}
|
|
40 \caption{Task Manager}
|
|
41 \label{fig:taskmanager}
|
|
42 \end{figure}
|
0
|
43
|
4
|
44 \section{Task の Scheduling}
|
15
|
45
|
|
46 GPU や Cell のような Shared Memory でない環境でのプログラミングを行う場合、
|
|
47 Task の入出力となるデータを転送し、転送が終わってから Task を起動しなければならない。
|
|
48 転送処理がボトルネックとなり、並列度が低下してしまう。
|
|
49 そのため、Cerium はパイプライン実行をサポートしている。
|
|
50
|
4
|
51 Scheduler に転送された Task はパイプラインで処理される(図:\ref{fig:scheduler})。
|
|
52 Task が全て終了すると Scheduler から TaskManager に mail を通して通知される。
|
|
53 通知に従い依存関係を解決した Task が再び TaskManager から Scheduler に転送される。
|
|
54
|
|
55 \begin{figure}[htpb]
|
|
56 \begin{center}
|
|
57 \includegraphics[scale=0.7]{./images/scheduler.pdf}
|
|
58 \end{center}
|
|
59 \caption{Scheduler}
|
|
60 \label{fig:scheduler}
|
|
61 \end{figure}
|
|
62 \newpage
|
|
63 \section{Task 生成の例}
|
|
64 ソースコード:\ref{src:createTask}に Task を生成する例題を示す。
|
|
65 input data を2つ用意し、 input data の各要素同士を乗算し、
|
|
66 output に格納する multiply という例題である。
|
|
67
|
|
68 \begin{lstlisting}[frame=lrbt,label=src:createTask,caption=Task の生成,numbers=left]
|
|
69 void
|
|
70 multiply_init(TaskManager *manager, float *i_data1, float *i_data2, float *o_data) {
|
|
71
|
|
72 // create task
|
|
73 HTask* multiply = manager->create_task(MULTIPLY_TASK);
|
|
74 multiply->set_cpu(spe_cpu);
|
|
75
|
|
76 // set indata
|
|
77 multiply->set_inData(0, i_data1, sizeof(float) * length);
|
|
78 multiply->set_inData(1, i_data2, sizeof(float) * length);
|
|
79
|
|
80 // set outdata
|
|
81 multiply->set_outData(0, o_data, sizeof(float) * length);
|
|
82
|
|
83 // set parameter
|
|
84 multiply−>set_param(0,(long)length);
|
|
85
|
|
86 // set device
|
|
87 multiply->set_cpu(SPE_ANY);
|
|
88
|
|
89 // spawn task
|
|
90 multiply−>spawn();
|
|
91 }
|
|
92 \end{lstlisting}
|
|
93
|
|
94 表:\ref{table:task_create_api}は Task 生成時に用いる API の一覧である。
|
|
95 create された Task は各種パラメタを設定し、spawn/iterate することで TaskManager に登録される。
|
0
|
96
|
4
|
97 \begin{tiny}
|
|
98 \begin{table}[htpb]
|
|
99 \begin{center}
|
|
100 \small
|
|
101 \begin{tabular}[htpb]{c|l}
|
|
102 \hline
|
|
103 create\_task & Task を生成する \\
|
|
104 \hline
|
|
105 set\_inData & Task への入力データのアドレスを追加 \\
|
|
106 \hline
|
|
107 set\_outData & Task からの出力データのアドレスを追加 \\
|
|
108 \hline
|
|
109 set\_param & Task へ値を一つ渡す。ここではlengthを渡している \\
|
|
110 \hline
|
|
111 set\_cpu & Task を実行する Device の設定 \\
|
|
112 \hline
|
|
113 spawn & 生成した Task を ActiveTaskList に登録する \\
|
|
114 \hline
|
|
115 \end{tabular}
|
|
116 \caption{Task 生成おける API}
|
|
117 \label{table:task_create_api}
|
|
118 \end{center}
|
|
119 \end{table}
|
|
120 \end{tiny}
|
0
|
121
|
4
|
122 ソースコード:\ref{src:createTask}は Host 側で Task を生成しているプログラムである。
|
|
123 Device 側で実行される Task (OpenCL、CUDA でいう kernel) の記述はソースコード:\ref{src:task}のようになる。
|
0
|
124
|
4
|
125 \begin{lstlisting}[frame=lrbt,label=src:task,caption=Task,numbers=left]
|
|
126 static int
|
|
127 run(SchedTask *s) {
|
|
128 // get input
|
|
129 float *i_data1 = (float*)s->get_input(0);
|
|
130 float *i_data2 = (float*)s->get_input(1);
|
|
131 // get output
|
|
132 float *o_data = (float*)s->get_output(0);
|
|
133 // get parameter
|
|
134 long length = (long)s->get_param(0);
|
|
135
|
|
136 // calculate
|
|
137 for (int i=0; i<length; i++) {
|
|
138 o_data[i] = i_data1[i] * i_data2[i];
|
|
139 }
|
|
140 return 0;
|
|
141 }
|
|
142 \end{lstlisting}
|
|
143
|
|
144 表:\ref{table:task_api}は Task 側で使用する API である。
|
|
145
|
|
146 \begin{tiny}
|
|
147 \begin{table}[htpb]
|
|
148 \begin{center}
|
|
149 \small
|
|
150 \begin{tabular}[htpb]{c|l}
|
|
151 \hline
|
|
152 get\_input & 入力データのアドレスを取得 \\
|
|
153 \hline
|
7
|
154 set\_output & 出力先データのアドレスを取得 \\
|
4
|
155 \hline
|
7
|
156 set\_param & パラメータを取得 \\
|
4
|
157 \hline
|
|
158 \end{tabular}
|
|
159 \caption{Task 側で使用する API}
|
|
160 \label{table:task_api}
|
|
161 \end{center}
|
|
162 \end{table}
|
|
163 \end{tiny}
|