view paper/chapter2.tex @ 15:712576635154

gpgpu
author Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 Feb 2015 11:32:28 +0900
parents 786db8c94c6e
children 79d16cee0afd
line wrap: on
line source

\chapter{Cerium}
Cerium は、当初 Cell 用の Fine-Grain TaskManager として当研究室で開発された。
本章では Cerium の実装について説明する。

\section{Cerium の概要}
Cerium は当初 Cell 用であったが、現在では Linux、 MaxOS X上で動作する。
GPGPU の Data Parallel を含めて同じ形式で記述できる。

CeriumはTaskManager、 SceneGraph、Rendering Engine の3つの要素から構成される。
本研究では Cerium の TaskManager を汎用計算フレームワークとして改良を行う。
これによりヘテロジニアス環境に対応したシステムやフレームワークに必要な API や機構について考察していく。
\section{Cerium TaskManager}
Cerium TaskManager では、処理の単位を Task としてプログラムを記述していく。
関数やサブルーチンを Task として扱い、 Task 間の依存関係を考慮しながら実行される。
Task を生成する際に、以下のような要素を設定することができる。

\begin{itemize}
\item input data
\item output data
\item parameter
\item cpu type
\item dependency
\end{itemize}

input/output data, parameter は関数で言うところの引数に相当する。
cpu type は Task が動作する Device を示し、 dependency は他の Task との依存関係を表す。

\section{Cerium における Task}
図:\ref{fig:taskmanager}は Cerium が Task を生成/実行する場合のクラスの構成図である。
TaskManager で依存関係が解消され、実行可能になった Task は ActiveTaskList に移される。
ActiveTaskList に移された Task は依存関係が存在しないのでどのような順番で実行されても良い。
Task は転送を行いやすい TaskList に変換され、cpu type に対応した Scheduler に転送される。
なお、転送はSynchronozed Queue である mail を通して行われる。


\begin{figure}[htpb]
  \begin{center}
    \includegraphics[scale=0.7]{./images/createTask.pdf}
  \end{center}
  \caption{Task Manager}
  \label{fig:taskmanager}
\end{figure}

\section{Task の Scheduling}

GPU や Cell のような Shared Memory でない環境でのプログラミングを行う場合、
Task の入出力となるデータを転送し、転送が終わってから Task を起動しなければならない。
転送処理がボトルネックとなり、並列度が低下してしまう。
そのため、Cerium はパイプライン実行をサポートしている。

Scheduler に転送された Task はパイプラインで処理される(図:\ref{fig:scheduler})。
Task が全て終了すると Scheduler から TaskManager に mail を通して通知される。
通知に従い依存関係を解決した Task が再び TaskManager から Scheduler に転送される。

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[scale=0.7]{./images/scheduler.pdf}
  \end{center}
  \caption{Scheduler}
  \label{fig:scheduler}
\end{figure}
\newpage
\section{Task 生成の例}
ソースコード:\ref{src:createTask}に Task を生成する例題を示す。
input data を2つ用意し、 input data の各要素同士を乗算し、
output に格納する multiply という例題である。

\begin{lstlisting}[frame=lrbt,label=src:createTask,caption=Task の生成,numbers=left]
void
multiply_init(TaskManager *manager, float *i_data1, float *i_data2, float *o_data) {
  
    // create task
    HTask* multiply = manager->create_task(MULTIPLY_TASK);
    multiply->set_cpu(spe_cpu);

    // set indata
    multiply->set_inData(0, i_data1, sizeof(float) * length);
    multiply->set_inData(1, i_data2, sizeof(float) * length);

    // set outdata
    multiply->set_outData(0, o_data, sizeof(float) * length);

    // set parameter
    multiply−>set_param(0,(long)length);
    
    // set device
    multiply->set_cpu(SPE_ANY);
    
    // spawn task
    multiply−>spawn();
}
\end{lstlisting}

表:\ref{table:task_create_api}は Task 生成時に用いる API の一覧である。
create された Task は各種パラメタを設定し、spawn/iterate することで TaskManager に登録される。

\begin{tiny}
  \begin{table}[htpb]
    \begin{center}
      \small
      \begin{tabular}[htpb]{c|l}
        \hline
        create\_task & Task を生成する \\
        \hline
        set\_inData & Task への入力データのアドレスを追加 \\
        \hline
        set\_outData & Task からの出力データのアドレスを追加 \\
        \hline
        set\_param & Task へ値を一つ渡す。ここではlengthを渡している \\
        \hline
        set\_cpu & Task を実行する Device の設定 \\
        \hline
        spawn & 生成した Task を ActiveTaskList に登録する \\
        \hline
      \end{tabular}
      \caption{Task 生成おける API}
      \label{table:task_create_api}
    \end{center}
  \end{table}
\end{tiny}

ソースコード:\ref{src:createTask}は Host 側で Task を生成しているプログラムである。
Device 側で実行される Task (OpenCL、CUDA でいう kernel) の記述はソースコード:\ref{src:task}のようになる。

\begin{lstlisting}[frame=lrbt,label=src:task,caption=Task,numbers=left]
static int
run(SchedTask *s) {
    // get input
    float *i_data1 = (float*)s->get_input(0);
    float *i_data2 = (float*)s->get_input(1);
    // get output
    float *o_data  = (float*)s->get_output(0);
    // get parameter
    long length = (long)s->get_param(0);

    // calculate
    for (int i=0; i<length; i++) {
        o_data[i] = i_data1[i] * i_data2[i];
    }
    return 0;
}
\end{lstlisting}

表:\ref{table:task_api}は Task 側で使用する API である。

\begin{tiny}
  \begin{table}[htpb]
    \begin{center}
      \small
      \begin{tabular}[htpb]{c|l}
        \hline
        get\_input & 入力データのアドレスを取得 \\
        \hline
        set\_output & 出力先データのアドレスを取得 \\
        \hline
        set\_param & パラメータを取得 \\
        \hline
      \end{tabular}
      \caption{Task 側で使用する API}
      \label{table:task_api}
    \end{center}
  \end{table}
\end{tiny}