view 14.tex @ 0:a9fda18657b3 default tip

add
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 16 Dec 2009 10:05:04 +0900
parents
children
line wrap: on
line source

\section{ 比較}

ここでは、SPURS Engine、Open CL、並列処理言語であるErlang/Scalaと比較してみる。

Cerium は、SPURS Engineの実装の一つであるが、SPURS Engine 自体の情報が
公開されていないので比較することは難しい。Cerium は、sourceforge.jp
上で公開されている。

Cerium では、SPE Task の終了を Mail により PPE に投げて、PPE側で Task
Queue の管理を行っている。Word countのような場合は、それが負荷になる
場合もある。SPURS Engine 等で、どのような工夫が行われているのかは
未知数である。

Open CLは、Taskを登録する代わりに、文字列として渡し、Open CL側で、
GPGPUやThreadに展開される。Mac OS X では、llvm \cite{llvm} を用いて
展開されている。Cerium では、前もってコンパイルされた関数をマクロ
により表に登録する仕組みである。

Kernel は、

{\small
\begin{verbatim}
    __kernel void UniformAddKernel(
        __global float *output_data, 
        __global float *input_data, 
        __local float *shared_data,
        const uint group_offset, 
        const uint base_index,
        const uint n)
    {
        const uint local_id = get_local_id(0);
        const uint group_id = get_global_id(0) 
            / get_local_size(0);
        const uint group_size = get_local_size(0);

\end{verbatim}
}

と言う形を持っている。globalがメインメモリ上のデータで、localが
Local Store のデータである。

データのload/storeは、Kernel として明示的に記述し、

{\small
{\small
\begin{verbatim}
    unsigned int k = PRESCAN_NON_POWER_OF_TWO;
    clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(cl_mem), &input_data);
    clEnqueueNDRangeKernel(ComputeCommands, 
               ComputeKernels[k], 1, 
         NULL, global, local, 0, NULL, NULL);
\end{verbatim}
}

}

等として、自分で Queue を管理する。実行 Queue に自分で格納する 
Open CL の方がやや繁雑な記述となる。

Kernel 間の依存関係は、Queue で解決されているので、起動する
メインルーチン側で処理することになる。

Kernelの中では、\_\_globalと言う形で、いつでもメインメモリにアクセスする
ことが可能である。なので、明示的なDMAは必要ない。しかし、見えないだけで
コストや待ち時間は生じてしまう。そこで、Pre Scan のような形で、
データを \_\_local に前もって持って来ておく必要がある。

\subsection{ Erlang, Scala}

Erlang と Scala は、Actor に似た感じで並列処理を行う。Erlang は、
Prolog に似た構文を持っており、Scala は Java 上に実装されている。

双方の言語とも通信はチャネルで行われて、Task 上のデータは関数型
言語的な意味で変更されない。再帰的な関数呼び出しにより、Taskの
状態を作るので、両方とも似たような(構文は隨分違うが)並列プログラミング
のスタイルを提供している。

Erlang

{\small
\begin{verbatim}
    ping(N, Pong_PID) ->
        Pong_PID ! {ping, self()},
        receive
            pong ->
                io:format("Ping received pong~n", [])
        end,
        ping(N - 1, Pong_PID).

\end{verbatim}
}

Scala
{\small
\begin{verbatim}
    class Counter extends Actor
    {
      override def act(): Unit = loop(0)
 
      def loop(value: Int): Unit = {
        receive {
          case Incr()   => loop(value + 1)
          case Value(a) => a ! value; loop(value)
          case Lock(a)  => a ! value
	      receive { case UnLock(v) => loop(v) }
          case _        => loop(value)
        }
      }
    }



\end{verbatim}
}

Cerium では、データの引き渡しは、void *にcastするので、型の
安全性を言語上で保証することは出来ない。Open CL でも状況は
同じで、

{\small
\begin{verbatim}
    __kernel void UniformAddKernel(
        __global float *output_data, 
        __global float *input_data, 
        __local float *shared_data,
        const uint group_offset, 
        const uint base_index,
        const uint n)

\end{verbatim}
}

が、
{\small
{\small
\begin{verbatim}
    err |= clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(cl_mem), &output_data);  
    err |= clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(cl_mem), &partial_sums);
    err |= clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(float),  0);
    err |= clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(cl_int), &group_offset);
    err |= clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(cl_int), &base_index);
    err |= clSetKernelArg(ComputeKernels[k],  
         a++, sizeof(cl_int), &n);
    err |= clEnqueueNDRangeKernel(ComputeCommands, 
      ComputeKernels[k], 1, NULL, 
           global, local, 0, NULL, NULL);
\end{verbatim}
}

}

などに相当することになる。これらの型を(IDE等で)チェックすることは、難しくはないが、
Scala のよう言語自体がチェックする方が望ましい。

Erlang, Scala は、GCを持っているが、Open CL/Cerium では、明示的なメモリ管理
を行う必要がある。

パイプライン処理をうまく動作させるには、Taskの列(Queue)を作る必要があるが、Erlang、
Scala では、その列を明示的に作ることは強制されていない。分散処理、あるいは、
Thread による並列処理には、Erlang, Scala が適しているが、Many Core 
では、さらになんらかの構文的なサポートが必要だと考えられる。