FPGA & GPU/OpenCL

インテルによるアルテラ買収のニュースは、これからのソフトウェア開発手法について何らかの変化があるのではないか、と思わせてくれます。
(http://systems.blue/blog/archives/25)

インテル、プログラマブルなLSI「FPGA」大手のアルテラ買収を発表。XeonにFPGAを組み込む計画も表明
http://www.publickey1.jp/blog/15/lsifpgaxeonfpga.html

メインCPU以外のプロセッサによる処理は、ゲーム機開発などでは当たり前ですが、私がそのパワーを体感したのはPlayStation2の開発のときでした。立体音響のマトリックス演算でしたが、メインCPUの何十倍の処理をやってのけました。
最近、前の記事でとりあげた言語処理だったり、機械学習などでも、GPUを活用する事例をよく見かけます。やはりこれからは、並列処理の考え方でプログラムを書く力が必要になるのでは、ということで、実際にプログラムを動かして頭をならしておこうと思い立ちました。

まずFPGAですが、Icarus Verilog というツールを使って、Ubuntu14.04 上で実行しました。ハードウェア記述言語ですが、シミュレーションしてくれます。

module test1;
	reg [31:0] i = 0, j = 0;
	reg clk = 1'b0;
	reg done = 1'b0;
	always @(posedge clk) begin
		i = i + 1;
		i = i + 1;
		j <= j + 1;
		j <= j + 1;
		if ( i >= 100 ) begin
			done = 1;
		end
	end
	initial begin
		clk = 0;
		while(!done) begin
			clk = 0; #10;
			clk = 1; #10;
		end
		$write("%d %d\n", i, j);
	end
endmodule

apt-get install iverilog
iverilog -o test1 test1.v
vvp test1

実行すると、100 と 50 が表示されます。
alwaysブロックがクロックのタイミングで呼び出されるのですが、ここにステータスを分けたりして、並列処理を書くようです。(データ並列・パイプライン並列) ここに複数の処理を書くために、通常のプログラムと違うしくみがあります。i はブロッキング代入、j はノンブロッキング代入といい、j は、alwaysブロックが終わった時点で確定されます。そのため、jはiの半分の値となっています。

参考 : インターフェイスZERO No.4

次に、OpenCLですが、OpenGL、OpenCVと似ていて間違えそうになりますが、違います。
同じようなものに、CUDAというのがありますが、NVIDIAのGPUでないと動作しないので、汎用性の高い方を選びました。またMacのXcodeが対応していることから、特にライブラリ、プラグイン等をインストールしなくてもいいので便利です。

opencl_xcode

このコードは下記OpenCL Sample Codesのものを実行しました。
https://iws44.iiita.ac.in/wiki/opencl/doku.php?id=mul24

Xcodeで動かすための修正点は、ヘッダ(OpenCL/opencl.h)とCLコードのファイルパス(絶対パス)です。
またGPUが対応していなくても、CL_DEVICE_TYPE_DEFAULTでデバイスを取得すれば実行できるみたいです。

// Step 02: Get information about the device
    err = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices );
    //err = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, &ret_num_devices );

kernel.clで受け取っているget_global_idは、worksizeで設定されている次元のそれぞれの数分、ループされます。このサンプルだと、yは1に固定されています。

// Step 11: Execute OpenCL kernel in data parallel
    size_t worksize[] = { MAT_SIZE, 1, 1 };
    clEnqueueNDRangeKernel( command_queue, kernel, 1, NULL, worksize, 0, 0, 0, 0 );
    err_check( err, "clEnqueueNDRangeKernel" );

このclEnqueueNDRangeKernelがkernel.clのプログラムを同時実行させますが、順番は保証されないようです。

GPGPU(General-purpose computing on graphics processing units)、
FPGA(field-programmable gate array)のどちらが、主流になっていくかわかりませんが、このようなプログラミングの考え方はもっとトレーニングしたいと思っています。

About

Categories: 未分類 タグ: ,