annotate paper/chapter5.tex @ 79:7990a2abbf05 default tip

add file
author Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
date Mon, 02 Mar 2015 11:21:40 +0900
parents f9b73e12a52f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
13
6277bb3a73e9 remove subsection
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 10
diff changeset
1 \chapter{GPGPU への対応}
77
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
2 Cerium の新たな演算資源として GPU の使用を可能にした。\cite{yuhi:2013a}
10
1519674c30ab dragon and firefly spec
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
3 現在、GPU のような異なる種類のアーキテクチャを搭載した CPU 、つまりヘテロジニアスな CPU が増えている。
1519674c30ab dragon and firefly spec
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
4 特定の計算に特化した Task の生成やスケジューリングを行い、 GPGPU により高い並列度を出す研究は様々な分野で行われている。
1519674c30ab dragon and firefly spec
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
5 本研究では Cerium を特定の計算に限らず、 GPU を用いて汎用計算を行えるフレームワークに改良する。
7
786db8c94c6e Bitonic sort example
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
786db8c94c6e Bitonic sort example
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
8 \section{OpenCL および CUDA による実装}
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
9 OpenCL 、CUDA による GPGPU 対応を行った。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
10 Scheduler と CpuThreads に対応させる形で
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
11 OpenCL を用いた GpuScheduler と GpuThreads、
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
12 CUDA を用いた CudaScheduler と CudaThreads を実装した。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
13 それぞれの Scheduler 内で各フレームワークの API を用いて GPU の制御を行っている。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
14
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
15 TaskManager から受け取った TaskList をもとに Device 上のメモリバッファを作成する。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
16 その後 CommandQueue、 Stream といったそれぞれの Queue に Device 制御用の Command を Queueing していく。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
17
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
18 Command は Queueing した順に実行されるので、以下のように Command を Queueing する。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
19 \begin{enumerate}
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
20 \item Host から Device へのデータ転送
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
21 \item kernel の実行
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
22 \item Device から Host へのデータ転送
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
23 \end{enumerate}
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
24
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
25 データの転送や kernel の実行は非同期 API を用いることで並列に行うことができる。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
26
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
27 通常、フレームワークが依存関係を解決して実行するが、
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
28 非同期 API を用いる場合はユーザが依存関係を考慮する必要がある。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
29 しかし Task の依存関係は TaskManager が既に解決した状態で送ってくるので、
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
30 Scheduler は依存関係を考慮せずに実行して問題ない。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
31
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
32 GPGPU 用の Scheduler は CommandQueue を2つ持っており、Task をパイプライン的に実行する。
50
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
33 GpuScheduler のパイプライン処理部分をソースコード:\ref{src:pipeline_gpu}に示す。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
34 \newpage
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
35 \begin{lstlisting}[frame=lrbt,label=src:pipeline_gpu,caption=GpuSchedulerにおけるパイプライン処理,numbers=left]
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
36 void
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
37 GpuScheduler::run() {
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
38 for (;;) {
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
39 memaddr params_addr = connector->task_list_mail_read();
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
40 // read task list mail from DmaManager
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
41
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
42 while (params_addr) {
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
43 // since we are on the same memory space, we don't has to use dma_load here
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
44 tasklist = (TaskListPtr)connector->dma_load(this, params_addr,sizeof(TaskList),
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
45 DMA_READ_TASKLIST);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
46
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
47 for (TaskPtr nextTask = tasklist->tasks; nextTask < tasklist->last();
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
48 nextTask = nextTask->next()) {
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
49
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
50 kernel[cur] = clCreateKernel(program, function, &ret);
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
51
50
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
52 int param = 1;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
53 for(int i=0;i<nextTask->inData_count;i++) {
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
54 ListElement *input_buf = nextTask->inData(i);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
55 if (input_buf->size==0) break;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
56 createBuffer(&memin[cur], param, context, mem_flag, input_buf->size, &ret);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
57 ret = clEnqueueWriteBuffer(command_queue[cur], memin[cur].buf[param],
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
58 CL_FALSE, 0, input_buf->size,
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
59 input_buf->addr, 0, NULL, NULL);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
60 ret = clSetKernelArg(kernel[cur], param, sizeof(memaddr),
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
61 (void *)&memin[cur].buf[param]);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
62 param++;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
63 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
64 memin[cur].size = param; // +1 means param
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
65
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
66 for(int i = 0; i<nextTask->outData_count;i++) { // set output data
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
67 ListElement *output_buf = nextTask->outData(i);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
68 if (output_buf->size==0) break;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
69 createBuffer(&memout[cur], i, context, CL_MEM_WRITE_ONLY, output_buf->size, &ret);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
70 ret = clSetKernelArg(kernel[cur], param,
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
71 sizeof(memaddr), (void *)&memout[cur].buf[i]);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
72 param++;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
73 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
74 memout[cur].size = param - memin[cur].size;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
75
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
76 ret = clEnqueueTask(command_queue[cur], kernel[cur], 0, NULL, NULL);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
77
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
78 for(int i=0;i<nextTask->outData_count;i++) { // read output data
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
79 ListElement *output_buf = nextTask->outData(i);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
80 if (output_buf->size==0) break;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
81 GpuBufferPtr mem = memout ;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
82 ret = clEnqueueReadBuffer(command_queue[cur], mem[cur].buf[i0], CL_FALSE, 0,
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
83 output_buf->size, output_buf->addr, 0,
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
84 NULL,&memout[cur].event[i]);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
85 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
86 cur++;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
87 if (STAGE <= cur) cur = 0;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
88 wait_for_event(kernel_event, memout, tasklist, cur);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
89 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
90 reply = (memaddr)tasklist->waiter;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
91 params_addr = (memaddr)tasklist->next;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
92 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
93
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
94 wait_for_event(kernel_event, memout, tasklist, cur);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
95
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
96 unsigned long long wait = 0;
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
97 (*connector->end_dmawait_profile)(&wait, &(connector->start_time), &(connector->stop_time));
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
98 connector->mail_write((memaddr)MY_SPE_STATUS_READY);
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
99 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
100 /* NOT REACHED */
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
101 }
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
102
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
103 \end{lstlisting}
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
104
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
105 \begin{itemize}
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
106 \item 4行目 : DMAManager から tasklist mail を取得
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
107 \item 9行目 : 取得した mail から TaskList を read をする。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
108 TaskList に格納されている Task 全てを実行し終わるまでループする
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
109 \item 15行目 : 二段のパイプラインを形成するため、kernel を2つ持作る
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
110 \item 18行目 : パイプラインの read 部分。input データを全て kernel の引数として MemoryBuffer に書き込み、
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
111 kernel に Buffer をset する
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
112 \item 31行目 : Output データを書き込む MemoryBuffer を用意し、kernel にset している。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
113 \item 40行目 : パイプラインの exec 部分。kernel を実行する
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
114 \item 42行目 : パイプラインの write 部分。kernel は実行した結果を MemoryBuffer に書き込む。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
115 MemoryBuffer に書き込まれた値をここで読み出している。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
116 \item 52行目 : パイプラインのステージの切り替えを行っている。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
117 wait\_for\_event 内で依存関係を解決したら実行の終わったステージの MemoryBuffer を delete し、次のステージへ移行する
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
118 \item 55行目 : 次の task を読み出し、このループを終了する
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
119 \end{itemize}
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
120
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
121 DMAManager から転送されてきた Task を読み込み、Input/Output データを取り出す。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
122 データは OpenCL の API を介して GPU の MemoryBuffer に送信され、kernel が実行される。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
123 実行終了後は MemoryBuffer から戻り値を読み取り、Cerium に Output データとして返している。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
124 一連の処理は CommandQueue を介して GPU で実行される。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
125 GpuScheduler は CommandQueue を2つ持っており、二段のパイプラインが形成される。
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
126
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
127 全ての Task が終了すると、
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
128 TaskManager 間の通信を担当する同期キューである mail を通して TaskManager に Task の終了を通知する。
50
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
129 終了が通知されると TaskManager でその TaskList に関する依存関係が解消される。
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
130
50
d4be7f4b9a73 add Gpu pipeline
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 35
diff changeset
131 Scheduler 内で Platform や Device ID の取得、 Context の生成、 Kernel の Build と Load等も行っており、
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
132 並列処理したい計算のみに集中できる。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
133
7
786db8c94c6e Bitonic sort example
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 \section{データ並列}
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
135 並列プログラミングにおいて、明示的な並列化部分はループ部分である。
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
136 GPU は数百個のコアを有しており、ループ部分に対してデータ並列で処理を行うことで CPU より高速に演算を行う事ができる。
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
137 プログラムの大部分がループであれば、データ並列による実行だけでプログラムの性能は向上する。
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
138
77
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 50
diff changeset
139 OpenCL 、 CUDA ともにデータ並列をサポートしている。\cite{yuhi:2014a}\cite{kkb:2014a}
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
140 OpenCL と CUDA はTask を実行する際にデータをどう分割するか指定し、
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
141 kernel にデータ並列用の処理を加えることで可能となる。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
142 \ref{sec:multicore_dataparallel}節で Cerium でマルチコア CPU におけるデータ並列を可能にした。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
143 GPGPU においてもデータ並列実行をサポートする。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
144 GPU 上でのデータ並列実行もマルチコア CPU と変わらず、iterate API によりデータ並列用の Task を生成することができる。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
145 iterate で Task を生成することで Scheduler が OpenCL 及び CUDA の API に適切なパラメタを渡している。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
146 Task の生成部分は マルチコア CPU と GPU で完全に同じ形式で記述できる。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
147
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
148 データ並列実行の際、Task は以下のように記述する。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
149 なお、例題は multiply を用いている。
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
150
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
151 \begin{lstlisting}[frame=lrbt,label=src:multiply_opencl,caption=Multiply(OpenCL),numbers=left]
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
152 __kernel void
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
153 multiply(__global const long *params,
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
154 __global const float *input1,
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
155 __global const float *input2,
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
156 __global const float *output) {
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
157
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
158 long id = get_global_id(0);
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
159
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
160 output[id] = input1[id] * input2[id];
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
161 }
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
162 \end{lstlisting}
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
163
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
164 \begin{lstlisting}[frame=lrbt,label=src:multiply_cuda,caption=Multiply(CUDA),numbers=left]
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
165 __global__ void
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
166 multiply(__global const long *params,
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
167 __global const float *input1,
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
168 __global const float *input2,
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
169 __global const float *output) {
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
170
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
171 int id = blockIdx.x * blockDim.x + threadIdx.x;
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
172
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
173 output[id] = input1[id] * input2[id];
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
174 }
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
175 \end{lstlisting}
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
176
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
177 このような Task を分割数分生成する。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
178 分割数は Task それぞれのフレームワークが用意している API を用いて指定する。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
179
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
180 \begin{itemize}
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
181 \item 自分の計算する範囲を取得(ソースコード\ref{src:multiply_opencl}、ソースコード\ref{src:multiply_cuda}の7行目)
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
182 \item 取得した範囲を計算(ソースコード\ref{src:multiply_opencl}、ソースコード\ref{src:multiply_cuda}の9行目)
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
183 \end{itemize}
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
184 いずれの Task も上記の手順で処理を行っている。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
185 計算する範囲について、 OpenCL では取得用の API を用い、 CUDA では kernel の持つ組み込み変数から算出する。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
186 マルチコア CPU では引数としてデータを直接渡していたが、OpenCL 、CUDA では上記の方法でメモリバッファから Load し、計算を行う。
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
187 値渡しや修飾子等若干の違いはあるが、OpenCL 、CUDA ともにマルチコア CPU(ソースコード:\ref{src:multicore_cpu}) とほぼ同じ形式で kernel を記述することができる。
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
188 CPU、 OpenCL、 CUDA いずれか1つの記述から残りのコードも生成できるようにする事が望ましい。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
189
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
190 データ並列で実行する場合、 Input と Output を各 Task 間で共有するため、少ないコピーに抑えられる。
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
191 CPU ではメモリ領域を節約する事はできるが、 Task と Manager でメモリ領域が同じ(\ref{sec:shared_memory}節)なため、
15
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
192 コピーによるオーバーヘッドは少ない。
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 13
diff changeset
193
35
7956856211c5 move data multicore-parallel from GPGPU-chapter to Multicore-chapter
Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
parents: 15
diff changeset
194 しかし GPU は SharedMemory ではなく、データの転送がオーバーヘッドとなるため、コピーを減らす事で並列度の向上が見込める。