Mercurial > hg > Papers > 2008 > gongo-sigos
view cerium-manager.tex @ 13:a91e95964045
*** empty log message ***
author | gongo |
---|---|
date | Thu, 27 Mar 2008 00:48:54 +0900 |
parents | fea1ac32de27 |
children | 091d888f7729 |
line wrap: on
line source
\subsection{Task Manager} Task Manager は、Task と呼ばれる分割された各プログラムを 管理するライブラリである。Task 同士の依存関係を考慮しながら メモリ上にマッピングし、SPE 上ではそのプログラムを DMA 転送によりロードする (\figref{fig-manager-load}) 。 SPE は 256KB という小さなデータ量しか持てず、 大量のプログラムを全て SPE 上に置いておくことはできない可能性がある。 そのため、必要な時に必要な実行プログラムだけが SPE 上にロード されていることが望ましい。 \begin{figure}[tb] \begin{center} \includegraphics[scale=0.45]{figure/manager-load.pdf} \caption{Task Manager} \label{fig-manager-load} \end{center} \end{figure} 現在実装されている Task Manager の API を \tabref{tab:manager-api} に示す。 \begin{table}[htbp] \caption{Task Manager API} \label{tab:manager-api} \hbox to\hsize{\hfil \begin{tabular}{r|l} \hline \hline create\_task & Task を生成する \\ \hline spawn & Task を実行 Task Queue に登録する \\ \hline set\_depend & Task の依存関係の考慮 \\\hline set\_cpu & Task を実行する CPU の設定 \\ \hline run & 実行 Task Queue の実行 \\ \hline \end{tabular}\hfil} \end{table} 以下に Task Manager を使った記述例を示す。 {\small \begin{verbatim} int main(void) { TaskManager *manager = new TaskManager; Task *task1, *task2; /** * cmd : 実行するタスクID * size : in_addr で取得するデータのバイト数 * in_addr : 入力データ元アドレス * out_addr : 出力データ先アドレス */ task1 = create_task(CMD_RUN1, size1, in_addr1, out_addr2); task2 = create_task(CMD_RUN2, size2, in_addr2, out_addr2); // task2 は task1 が終了してから開始する task2->set_depend(task1); task1->spawn(); task2->spawn(); manager->run(); return 0; } \end{verbatim} } \subsubsection{Task の定義} タスクの定義を以下に示す。 {\small \begin{verbatim} class Task { public: int command; int size; unsigned int in_addr; unsigned int out_addr; struct task *self; }; class HTask : public Task { public: TaskQueue wait_me; TaskQueue wait_i; CPU_TYPE cpu_type; }; \end{verbatim} } Task クラスは SPE が実行するタスクの単位オブジェクトである。 SPE はメインメモリの \verb|in_addr| から DMA で入力データを取得し、 command に対応するコードを実行し、 結果を メインメモリの \verb|out_addr| に DMA で送信する。 これらの処理はパイプラインに沿って動作する (\ref{sec:pipeline}) 。 HTask クラスは TaskManager で管理する実行前のタスクオブジェクトである。 \verb|wait_me, wait_i| はタスク依存の条件 (\ref{sec:task}) に、 \verb|cpu_type| は PPE と SPE のタスクの切り替え (\ref{sec:change}) に用いる。 \subsubsection{スケジューラ} \label{sec:pipeline} Cell ではそれぞれのコアがメインメモリを 直接参照することは出来ず、DMA 転送によりデータをやりとりする。 DMA は CPU を介さず直接データ転送を行う方式である。 SPE は DMA 完了を待たずに他の処理を行うことが出来るので、 DMA のレイテンシを隠すことが出来る。 また、ダブルバッファリングを行うことで パイプライン処理が可能となる (\figref{fig-pipeline}) 。 \begin{figure}[tb] \begin{center} \includegraphics[scale=0.43]{figure/pipeline.pdf} \caption{Pipeline} \label{fig-pipeline} \end{center} \end{figure} パイプライン処理を入れた Task Manager の Scheduler を以下に示す。 \begin{verbatim} do { task3->write(); task2->exec(); task1->read(); taskTmp = task3; task3 = task2; task2 = task1; task1 = task1->next(this, taskTmp); } while (task1); \end{verbatim} Task Manager を \figref{fig-cerium} に適用させると、 \figref{fig-manager-pipeline} のようにパイプライン的に動作する。 \begin{figure}[tb] \begin{center} \includegraphics[scale=0.36]{figure/manager-pipeline.pdf} \caption{Task Manager が行う Pipeline} \label{fig-manager-pipeline} \end{center} \end{figure} \subsubsection{Dependency} \label{sec:task} Task Manager はタスク依存を解決する機能を持っている。 以下は記述例である。 \begin{verbatim} // task2 は task1 が終了してから開始する task2->set_depend(task1); \end{verbatim} タスク依存が満たされたものをアクティブキューにいれ、SPE を起動する。 SPE はアクティブキューから、処理するコードとデータを取得し、 自律的に実行を行う。 終了したタスクは PPE に対して終了のコマンドを発行し、PPE はそれを見て ウェイトキューのタスクを調べ、タスク依存を満たしたものが出てきたら アクティブキューに入れ、SPE を再び起動する。 \subsubsection{PPE コードと SPE コードの互換性} \label{sec:change} Cerium では、 SPE を用いる Cell 上でのみ動作するプログラムの他に、 Linux や Mac OS X などで動く、アーキテクチャに依存しないプログラムを 記述することが可能である。 依存しないプログラムの場合、スケジューラはもちろんメインメモリ上で 動作する。パイプライン処理は SPE と {\small \begin{verbatim} task1->set_cpu(CPU_PPE); // PPE 上で実行される task2->set_cpu(CPU_SPE); // SPE 上で実行される \end{verbatim} } \subsubsection{PPE と SPE 間の同期} \ref{sec:task} で述べたように、PPE から SPE へはタスクの実行命令を、 SPE から PPE へはタスクの終了などを伝える必要がある。 その際、待ち合わせを行うと処理が止まってしまい、並列度が下がってしまう。 Cell では、PPE と SPE 間のメッセージのやりとりには Mailbox という FIFO メッセージキューを用いることができる。 メッセージ交換なので待ち合わせを避けることが可能である。 %%PPE が SPE からメールを受け取る場合、 %%\verb|spe_out_mbox_read()| という、 %%SPE Runtime Management Library \cite{libspe2} を用いる。 %%しかし、\verb|spe_out_mbox_read()| は Non-blocking function のため、 %%busy-wait なメールの待ち方は避けるべきである。 %%今回は、PPE 側でメールチェックを行う際に、SPE からのメールをチェックする。 %% %%PPE と SPE のメールチェックを分離させたい場合、 %%メールをチェックする Blocking Function を作る必要がある。 %% %%もしくは SPE Event Handling を用いる手法もある。 %%これは、メールが来たら event を起こすことを Event Handler に登録する。 %%この場合、通常の Mailbox ではない、割り込み用の interrupting Mailbox を %%使用しなくてはならない。 %%interrupting Mailbox を使用する spe\_out\_intr\_mbox\_read() は、 %%Event が起きたときに呼ばれるため Blocking Function である。 %%SPE のどれかからメッセージが来たらポーリングによってメールチェックを行う。 %% %%今回は、PPE と SPE のメールチェックは分離しない実装をした。 %%