view paper/compare.tex @ 0:fd9154e03f46

thesis
author e065725@kinjyo.cr.ie.u-ryukyu.ac.jp
date Sat, 13 Feb 2010 21:38:25 +0900
parents
children
line wrap: on
line source

\chapter{比較} \label{chapter:compare}

ここでは Khronos OpenCL Working Group が開発している、
並列プログラミングのフレームワークである OpenCL 及び、
Cell で動作する OpenGL のドライバである Gallium3D について説明し、
TaskManager 、Cerium との比較を行う。

\section{OpenCL}

OpenCL (Open Computing Language) \cite{opencl} とは、
マルチコアCPU や GPU、その他のプロセッサによる、
ヘテロジニアスコンピューティングのフレームワークである。
OpenCL C プログラミング言語は ISO/IEC 9899:1999 (C99) 規格を
ベースとしている。

OpenCL のプラットフォームモデルは \figref{cp_opencl_plat} のようになり、
一つの Host と複数の OpenCL Device で構成されている。
OpenCL devices の中では Compute Units (CUs) として分割され、その中でさらに
Processing Elements (PEs) として分割される。

\begin{figure}[htb]
  \begin{center}
    \includegraphics[scale=0.7]{images/cp_opencl_plat.pdf}
    \caption{OpenCL Platform}
    \label{fig:cp_opencl_plat}
  \end{center}
\end{figure}

OpenCL アプリケーションでは、実行する処理 command が Host から 
PEs へ送られる。PEs では SIMD (Single Instruction Multiple Data)
もしくは SPMD (Single Program Multiple Data) で実行される。

OpenCL devices や Host には kernel があり、Host kernel では
OpenCL devices context や実行 command の管理、OpenCL device kernel では
Host から送られて来た実行 command の処理を行う。
Host は OpenCL devices での kernel の実行を調整するために、
command-queue を生成し context へ渡す。
command-queue には以下の command がある。

\begin{itemize}
\item Kernel execution commands \\
  実行コマンド queue
\item Memory commands \\
  データの送受信に関する情報(Host アドレス空間)
\item Synchronization commands \\
  command の依存や同期等に関する情報
\end{itemize}

また、OpenCL Device は4つの違うメモリ領域(Global Memory、Constant Memory、
Local Memory、Private Memory)を持ち、それぞれ Host や CUs、PEs からの
アクセス権限が異なる (アドレス空間が異なる)。

プログラミングモデルとしては、データ並列、タスク並列をサポートしている。

OpenCL は Host や 各 device に kernel があることや、
device 毎にメモリアドレス空間が違う、プログラミングモデル等、
TaskManager とよく似ている。

OpenCL は汎用的な実装となっているため、
例えばタスクのメモリアクセス API も複雑な記述となっている。
対して TaskManager は、現在 Cell 環境に重きを置いているため、
メモリアクセスは DMA に対応した記述が行われる。
DMA では明示的にアドレスを指定することになるので、
OpenCL よりも簡潔な記述が可能となっている。
このことから、TaskManager は OpenCL の軽めな実装の一つという捉え方も出来る。

OpenCL に対して TaskManager が優れている点は、Mac OS X や Linux、
Cell といった複数の環境で動作することによる信頼性の確保のしやすさにある。
TaskManager では、タスク毎に実行する CPU を選択できるため、
動作環境が変わっても大幅なコードの変更が必要なく、
Single Core プログラムとして動作させることができる。
これにより、タスク単体やそれらを繋げたプログラム全体を
逐次型プログラムと見なし、二分法などのデバッグ手法を用いることが出来る。
このことは \figref{manycore_step} のような段階に沿って
開発が可能になることに繋がる。

\section{Gallium}

Gallium3D \cite{gallium} とは Tungsten Graphics 社が開発している、
オープンソースの 3D グラフィックドライバ である。
現在、Gallium には Intel GPU (i915) と Cell のドライバが実装されており、
OSMesa \cite{osmesa} ではこの Cell ドライバを用いている。
現在の Cell Driver のバージョンは 0.2 で、
Cell SDK (Software Development Kit) の version 2.1 もしくは 3.0が 必要となる。

Gallium Cell Driver では、Triangle を SPE に送り、
そこから得られた Span に対してテクスチャを貼りレンダリングする。
この時、Tile と呼ばれる、分割した描画領域毎に FrameBuffer へ書き込む。
SPE は 6 個使用しており、SPE 上では SIMD 演算を積極的に使用している。

我々がレンダリングエンジンとして OSMesa を採用しなかった理由は
先行研究 \cite{akira} で述べられているように、
OSMesa の実装自体が非常に複雑で、SPE を使用するための拡張が困難であると
判断したからである。
その OSMesa の Cell 実装として OpenGL のドライバである Gallium が登場した
ことにより、レンダリングエンジンとして Gallium を採用することを考えた。
しかし、Cell 上でのゲーム開発において、
レンダリングエンジンのみを SPE 上に実装しても、
Amdahl 則を考慮すると並列度の確保が困難であると考えられる。
よって、我々はレンダリングエンジンとして Gallium を採用せず、
レンダリングだけではなく SceneGraph の動作も SPE 上で行わせる
Cerium の開発を行っている。

\subsection{実行速度比較}

Cerium は OSMesa のレンダリング実装を参考にしているため、
Gallium と同様のレンダリングを行っている。
ここでは、Cerium と Gallium の実行速度を計測し比較した。
例題プログラムとして、\figref{cerium_sg_example} の地球のオブジェクトを
表示して (\figref{com_gallium}) 、SDL から得られる実行時間を元に
FPS (Frame Per Second) を出力して比較する。解像度は 1920x1080 とする。
Gallium、Cerium それぞれで以下のような実行環境を構築している。

\begin{figure}[htb]
  \begin{center}
    \includegraphics[scale=0.2]{images/com_gallium.pdf}
    \caption{Gallium、Cerium 例題}
    \label{fig:com_gallium}
  \end{center}
\end{figure}

\subsubsection{実行環境構築 Gallium}

Gallium の例題プログラムでは、Cell Driver が組み込まれている
OpenGL library (libGL) をロードして実行する。
また、\ref{sec:cerium_sg_xml} 節で説明した xml ファイル を用いて
OpenGL の API で表示するルーチンは同研究室の杉山が実装した。
以下がそのコードとなる。

\begin{verbatim}
void
SceneGraph::gl_draw(void)
{
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, (GLuint)texture);

  glTranslatef(xyz[0], xyz[1], xyz[2]);

  glTranslatef(c_xyz[0], c_xyz[1], c_xyz[2]);
  glRotatef(angle[0], 1, 0, 0);
  glRotatef(angle[1], 0, 1, 0);
  glRotatef(angle[2], 0, 0, 1);
  glTranslatef(-c_xyz[0], -c_xyz[1], -c_xyz[2]);

  glBegin( GL_TRIANGLES);
  for(n = 0; n < size*3; n += 3) {
      glTexCoord2f(tex_pos[n], 1-data[n+1]);
      glVertex3f(coord[n], coord[n+1], coord[n+2]);
      glNormal3f(normal[n], normal[n+1], normal[n+2]);
  }
  glEnd();
  glDisable(GL_TEXTURE_2D);
}
\end{verbatim}

\subsubsection{実行環境構築 Cerium}

Cerium の描画出力は SDL Window と FrameBuffer の二種類ある。
FrameBuffer では、SPE から直接 FrameBuffer へ DMA 転送により書き込むが、
SDL Window 経由では、一度 PPE の バッファ (SDL\_Surface) へ書き込んでから
FrameBuffer へ書き込む。以下がそのコードとなる。
通常、SDL を用いる場合はこの様なコードになる。

\begin{verbatim}
  // bitmap : RGB値を持つ バッファ (SPE から書き込まれる)
  // screen : FrameBuffer のアドレスを指す
  SDL_BlitSurface(bitmap, NULL, screen, NULL);
  SDL_UpdateRect(screen, 0, 0, 0, 0);
\end{verbatim}

\subsection{実行結果と考察}

各環境の実行結果を \tabref{com_gallium} に示す。
コンパイラの最適化レベルは -O9 を用いている。

\begin{table}[htb]
  \begin{center}
    \caption{Gallium、Cerium 実行速度比較結果} \label{tab:com_gallium}
    \hbox to\hsize{\hfil
      \begin{tabular}{l|l} \hline \hline
        Gallium (SPE 6個) & {\bf 5.4 FPS} \\ \hline
        \hline
        Cerium (SDL 出力、SPE 1個) & 2.2 FPS \\ \hline
        Cerium (FrameBuffer 出力、SPE 1個) & 2.5 FPS \\ \hline
        Cerium (SDL 出力、SPE 6個) & 6.7 FPS \\ \hline
        Cerium (FrameBuffer 出力、SPE 6個) & {\bf 9.5 FPS} \\ \hline
      \end{tabular}\hfil}
  \end{center}
\end{table}

結果から、SPE の数が同じ場合は Cerium の方が Gallium よりも実行速度が
速いと確認できた。
また、直接 FrameBuffer に書き込む方が速いことも確認できる。

Cerium では光源やシェーディング、アルファブレンディングなどの処理は
行っておらず、現在は最低限のレンダリング機能しか実装していないため
速度に差が出たのではないかと考えられる。
しかし、Gallium と違い Cerium は SIMD 演算をまだ組み込んでいないため、
%各種レンダリング機能を追加したとしても、
さらに速度向上が期待できる。