スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

エラーの原因を探っているうちに分かった副産物

例のごとくUbuntu + NVIDIA CUDA toolkit 4.1環境で自作のOpenCLプログラムを実行しようとしていたのだが、どうもclBulidProgramがCL_INVALID_VALUEエラーで失敗するという現象が起きて、これの原因を理解するのに数日かかってしまった。

結果から言うと原因は単純で、OpenCLカーネルに__constant指定した引数を多く渡しすぎていたのがいけなかった。OpenCLには実行環境依存で、__constant引数の個数に上限がある。これは

clGetDeviceInfo()の引数に CL_DEVICE_MAX_CONSTANT_ARGS を指定して問い合わせを行うことで調べることができる。私の開発環境(GeForce GT440)では、この値は9だった。問題のカーネルコードを見ると、確かに__constant引数が10個もあったので、これをいくつかを__global指定に戻したところ問題は解消した。

こんな簡単なことに気づくのに数日要してしまうとは、やれやれ…この問題を直接指摘するエラーメッセージが何も出力されず、CL_INVALID_VALUEしか手がかりがなかったのでずいぶんと手間をかけてしまった。

しかしまあ、調べる過程で副産物というか、結果的には全然今回の件では必要なかったが、後々で役立ちそうな知識も若干分かったので、せっかくであるからメモしておくとしよう。

1. OpenCLのカーネル用のスタンドアローンコンパイラ
OpenCL環境では、実行環境の中に組み込まれたカーネルコードコンパイラがアプリケーション実行時にソースを読み込んでコンパイルを行う(あらかじめ用意されたコンパイル済みプログラムを読み込む場合もあるが)ので、基本的にはスタンドアローンコンパイラが存在しない。NVIDA CUDA toolkitでも、nvccはCUDA Cのコンパイル用であって、スタンドアローンでOpenCLのカーネルをコンパイルすることはできない。

しかし実行環境内部ではコンパイルが行われている以上、うまくすればこの結果を取り出すことは可能なはずである。このような考えに基づいて、Linux + NVIDIA CUDA toolkit上で動作するスタンドアローンコンパイラを作成した人がいることを発見した。

ClusterChimps.org

というサイトの「サル知恵」(Ape knowledge)メニューからOpenCL toolkitの項を選ぶと、画面左側に"Download tarball"のリンクが現れる。ここからocltools-1.0.tar.gzをダウンロードして、ソースをコンパイル、インストールすればスタンドアローンコンパイラが使えるようになるようだ。

前提として、
libssl-dev
libboost-program-options-devパッケージ
CUDA toolkit(4.1で動作確認)

がインストールされていなければならない。その上で、私が自分の環境でコンパイルを行うには以下の若干の調整が必要であった。

export BOOST_CFLAGS=-I/usr/include
export CFLAGS=-I/usr/local/cuda/include
export CPPFLAGS=-I/usr/local/cuda/include
export LDFLAGS=-lcrypto

以上の環境変数を設定した上で、

./configure --prefix=/usr/local/ocltools

を実行し、さらに各(サブ)ディレクトリにあるMakefile内部のBOOST_LIBSのところがバージョン依存になっているので、

BOOST_LIBS = -lboost_program_options

と修正しておく。

これで

make
sudo make install

を実行すれば /usr/local/ocltools/bin にバイナリがインストールされる。後はこのディレクトリを自分のPATHに追加でもしておけばよい。

実行するには、例えばreductionSum.clというカーネルソースをコンパイルしたければ

oclcc -o reductionSum.ptx --cl-nv-verbose reductionSum.cl

などとすれば、PTXファイルが作成される。これの中身はGPU用のアセンブラコードである。コンパイラに渡すことのできるフラグはOpenCLのclBuildProgramに指定できるもの(に一つ余分に"-"を前置したもの)である。上記の例の用に"nv"を含んでいるのはベンダー依存のフラグなのでNVIDIAのドキュメントを参照する必要がある。

2. NVIDIA CUDA toolkitのコンパイルキャッシュ
OpenCLにせよCUDAにせよ、NVIDIAの実行環境では、カーネルソースをコンパイルした中間結果をホームディレクトリ以下の".nv/ComputeCache"ディレクトリに保存、再利用するようだ。(Windowsでも類似のフォルダにキャッシュが作成される)。何らかの理由でこの働きを抑制したい場合、環境変数CUDA_DISABLE_CACHEを"1"に設定しておけばよい。私は確認していないがフォーラムには、#includeであるカーネルソースから別のカーネルソースを読み込んでいる場合正しく更新が反映されないという投稿もあったので、この設定が役立つ場合もあるかもしれない。ただしキャッシュファイルを無効にするので、当然コンパイルには毎回若干時間がかかる。
スポンサーサイト
プロフィール

GM3D

Author:GM3D
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。