changeset 50:d4be7f4b9a73

add Gpu pipeline
author Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
date Tue, 17 Feb 2015 05:07:25 +0900
parents c7678996940c
children e2790efcd306 8057614d5b77
files paper/chapter5.tex paper/chapter6.tex paper/master_paper.pdf paper/master_paper.toc
diffstat 4 files changed, 116 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/paper/chapter5.tex	Tue Feb 17 03:53:19 2015 +0900
+++ b/paper/chapter5.tex	Tue Feb 17 05:07:25 2015 +0900
@@ -30,12 +30,105 @@
  Scheduler は依存関係を考慮せずに実行して問題ない。
 
 GPGPU 用の Scheduler は CommandQueue を2つ持っており、Task をパイプライン的に実行する。
+GpuScheduler のパイプライン処理部分をソースコード:\ref{src:pipeline_gpu}に示す。
+\newpage
+\begin{lstlisting}[frame=lrbt,label=src:pipeline_gpu,caption=GpuSchedulerにおけるパイプライン処理,numbers=left]
+void
+GpuScheduler::run() {
+  for (;;) {
+    memaddr params_addr = connector->task_list_mail_read();
+    // read task list mail from DmaManager
+    
+    while (params_addr) {
+      // since we are on the same memory space, we don't has to use dma_load here
+      tasklist = (TaskListPtr)connector->dma_load(this, params_addr,sizeof(TaskList),
+                                                  DMA_READ_TASKLIST);
+                                                  
+    for (TaskPtr nextTask = tasklist->tasks; nextTask < tasklist->last();
+         nextTask = nextTask->next()) {
+                   
+            kernel[cur] = clCreateKernel(program, function, &ret);
 
-転送されてきた Task が全て終了すると、 
+            int param = 1;
+            for(int i=0;i<nextTask->inData_count;i++) {
+                ListElement *input_buf = nextTask->inData(i);
+                if (input_buf->size==0) break;
+                createBuffer(&memin[cur], param, context, mem_flag, input_buf->size, &ret);
+                ret = clEnqueueWriteBuffer(command_queue[cur], memin[cur].buf[param],
+                                           CL_FALSE, 0, input_buf->size,
+                                           input_buf->addr, 0, NULL, NULL);
+                ret = clSetKernelArg(kernel[cur],  param, sizeof(memaddr),
+                                     (void *)&memin[cur].buf[param]);
+                param++;
+            }
+            memin[cur].size  = param; // +1 means param
+            
+            for(int i = 0; i<nextTask->outData_count;i++) { // set output data
+                ListElement *output_buf = nextTask->outData(i);
+                if (output_buf->size==0) break;
+                createBuffer(&memout[cur], i, context, CL_MEM_WRITE_ONLY, output_buf->size, &ret);
+                ret = clSetKernelArg(kernel[cur],  param,
+                                     sizeof(memaddr), (void *)&memout[cur].buf[i]);
+                param++;
+            }
+            memout[cur].size = param - memin[cur].size;
+
+            ret = clEnqueueTask(command_queue[cur], kernel[cur], 0, NULL, NULL);
+                
+            for(int i=0;i<nextTask->outData_count;i++) { // read output data
+                ListElement *output_buf = nextTask->outData(i);
+                if (output_buf->size==0) break;
+                GpuBufferPtr mem = memout ;
+                ret = clEnqueueReadBuffer(command_queue[cur], mem[cur].buf[i0], CL_FALSE, 0,
+                                          output_buf->size, output_buf->addr, 0,
+                                          NULL,&memout[cur].event[i]);
+                }
+            cur++;
+            if (STAGE <= cur) cur = 0;
+            wait_for_event(kernel_event, memout, tasklist, cur);
+         }
+         reply = (memaddr)tasklist->waiter;
+         params_addr = (memaddr)tasklist->next;
+      }
+
+      wait_for_event(kernel_event, memout, tasklist, cur);
+    
+      unsigned long long wait = 0;
+      (*connector->end_dmawait_profile)(&wait, &(connector->start_time), &(connector->stop_time));
+      connector->mail_write((memaddr)MY_SPE_STATUS_READY);
+    }
+    /* NOT REACHED */
+}
+
+\end{lstlisting}
+
+\begin{itemize}
+\item 4行目 : DMAManager から tasklist mail を取得
+\item 9行目 : 取得した mail から TaskList を read をする。 
+  TaskList に格納されている Task 全てを実行し終わるまでループする
+\item 15行目 : 二段のパイプラインを形成するため、kernel を2つ持作る
+\item 18行目 : パイプラインの read 部分。input データを全て kernel の引数として MemoryBuffer に書き込み、
+  kernel に Buffer をset する
+\item 31行目 : Output データを書き込む MemoryBuffer を用意し、kernel にset している。
+\item 40行目 : パイプラインの exec 部分。kernel を実行する
+\item 42行目 : パイプラインの write 部分。kernel は実行した結果を MemoryBuffer に書き込む。
+  MemoryBuffer に書き込まれた値をここで読み出している。
+\item 52行目 : パイプラインのステージの切り替えを行っている。
+  wait\_for\_event 内で依存関係を解決したら実行の終わったステージの MemoryBuffer を delete し、次のステージへ移行する
+\item 55行目 : 次の task を読み出し、このループを終了する
+\end{itemize}
+
+DMAManager から転送されてきた Task を読み込み、Input/Output データを取り出す。
+データは OpenCL の API を介して GPU の MemoryBuffer に送信され、kernel が実行される。
+実行終了後は MemoryBuffer から戻り値を読み取り、Cerium に Output データとして返している。
+一連の処理は CommandQueue を介して GPU で実行される。
+GpuScheduler は CommandQueue を2つ持っており、二段のパイプラインが形成される。
+
+全ての Task が終了すると、
 TaskManager 間の通信を担当する同期キューである mail を通して TaskManager に Task の終了を通知する。
-終了が通知されると TaskManager でその TaskList に関する依存関係が解消され、
+終了が通知されると TaskManager でその TaskList に関する依存関係が解消される。
 
-GPGPU の Scheduler 内で Platform や Device ID の取得、 Context の生成、 Kernel の Build と Load等も行っており、OD
+Scheduler 内で Platform や Device ID の取得、 Context の生成、 Kernel の Build と Load等も行っており、
 並列処理したい計算のみに集中できる。
 
 \section{データ並列}
--- a/paper/chapter6.tex	Tue Feb 17 03:53:19 2015 +0900
+++ b/paper/chapter6.tex	Tue Feb 17 05:07:25 2015 +0900
@@ -136,7 +136,7 @@
     \includegraphics[scale=0.7]{./images/iothread.pdf}
   \end{center}
   \caption{IO Thread による BlockedRead}
-  \label{fig:iothread__blockedread}
+  \label{fig:iothread_blockedread}
 \end{figure}
 IO\_0 で実行される Task は BlockedRead のみなので、
 IO\_0 のpriority を高く設定することで Blocked Read は連続で実行される。
Binary file paper/master_paper.pdf has changed
--- a/paper/master_paper.toc	Tue Feb 17 03:53:19 2015 +0900
+++ b/paper/master_paper.toc	Tue Feb 17 05:07:25 2015 +0900
@@ -21,22 +21,22 @@
 \contentsline {section}{\numberline {5.3}データ並列}{20}
 \contentsline {chapter}{\numberline {第6章}GPGPU への対応}{23}
 \contentsline {section}{\numberline {6.1}OpenCL および CUDA による実装}{23}
-\contentsline {section}{\numberline {6.2}データ並列}{24}
-\contentsline {chapter}{\numberline {第7章}並列処理向けI/O}{26}
-\contentsline {section}{\numberline {7.1}mmap}{26}
-\contentsline {section}{\numberline {7.2}Blocked Read による I/O の並列化}{27}
-\contentsline {section}{\numberline {7.3}I/O 専用 Thread の実装}{29}
-\contentsline {chapter}{\numberline {第8章}ベンチマーク}{30}
-\contentsline {section}{\numberline {8.1}実験環境}{30}
-\contentsline {section}{\numberline {8.2}マルチコア}{31}
-\contentsline {section}{\numberline {8.3}GPGPU}{33}
-\contentsline {section}{\numberline {8.4}並列 I/O}{35}
-\contentsline {chapter}{\numberline {第9章}既存のプログラミングフレームワークとの比較}{37}
-\contentsline {section}{\numberline {9.1}OpenCL}{37}
-\contentsline {section}{\numberline {9.2}CUDA}{38}
-\contentsline {section}{\numberline {9.3}StarPU}{39}
-\contentsline {chapter}{\numberline {第10章}結論}{41}
-\contentsline {section}{\numberline {10.1}今後の課題}{42}
-\contentsline {chapter}{謝辞}{43}
-\contentsline {chapter}{参考文献}{44}
-\contentsline {chapter}{発表文献}{45}
+\contentsline {section}{\numberline {6.2}データ並列}{26}
+\contentsline {chapter}{\numberline {第7章}並列処理向けI/O}{28}
+\contentsline {section}{\numberline {7.1}mmap}{28}
+\contentsline {section}{\numberline {7.2}Blocked Read による I/O の並列化}{29}
+\contentsline {section}{\numberline {7.3}I/O 専用 Thread の実装}{31}
+\contentsline {chapter}{\numberline {第8章}ベンチマーク}{32}
+\contentsline {section}{\numberline {8.1}実験環境}{32}
+\contentsline {section}{\numberline {8.2}マルチコア}{33}
+\contentsline {section}{\numberline {8.3}GPGPU}{35}
+\contentsline {section}{\numberline {8.4}並列 I/O}{37}
+\contentsline {chapter}{\numberline {第9章}既存のプログラミングフレームワークとの比較}{39}
+\contentsline {section}{\numberline {9.1}OpenCL}{39}
+\contentsline {section}{\numberline {9.2}CUDA}{40}
+\contentsline {section}{\numberline {9.3}StarPU}{41}
+\contentsline {chapter}{\numberline {第10章}結論}{43}
+\contentsline {section}{\numberline {10.1}今後の課題}{44}
+\contentsline {chapter}{謝辞}{45}
+\contentsline {chapter}{参考文献}{46}
+\contentsline {chapter}{発表文献}{47}