その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

CUDAのエラーチェックを楽にする

CUDAの組み込み関数はほとんどcudaError_tというエラーコードのenumの値を返してくるので,これを適宜見てエラー処理をする必要があります.最近ではそこまででもないですが,CUDAの組み込み関数はカジュアルにエラーを吐くのでちゃんと見てやらなければならない.
見てやると言っても,CUDAの組み込み関数がエラーを吐いてきたらほとんどの場合そのまま潔く死んで欲しいので (個人の意見),以下の様に戻り値をチェックしてexit()するというコードを大量に書くことになります.

int *foo;
cudaError_t err;
err = cudaMalloc((void **)&foo, sizeof(int) * 42);
if (err != cudaSuccess) {
    exit(err);
}
...

まあ,素直に書けばええやん! という意見は尤もなのですが,いかんせんこういうエラーチェックが大量に入ると本質的なコードが追いにくくなってつらい.
あとカジュアルにエラーチェックを忘れてしまって,バグッた時にハマる (しかしまあ,これはもうどうしようもない気がしている).golangとかだと,返ってきたerrが使われてないと「err使われてないよ! (つまりエラー処理してないんじゃねえの!)」と処理系が叱ってくれるからナイスですね.羨ましい.あとgolangは「エラーを受け取っても受け取らなくても良いよ」みたいなものが無いから,そこら辺のコードを規約化出来て良いという印象があります.


さて,そうしたリッチな機構が無い上でどうするかというと,僕は以下の様なマクロを書いてしのいでいます.

でもって,こう書く

int *foo;
CUDA_SAFE_CALL( cudaMalloc((void **)&foo, sizeof(int) * 42) );

こうしておくと,CUDA組み込み関数からエラーが吐かれた時にエラーメッセージ・ファイル名・行番号と共に,エラーコードでexit()してくれるのでまあまあ便利.
ちなみにcudaGetErrorString()っていう関数はcudaError_tの値をもとにエラーメッセージを引っ張ってきてくれる君です.


しかし,これも野蛮な方法であることには違いないし (なにより,CUDAの組み込み関数がCUDA_SAFE_CALLに渡される事が保証されない),エラーチェックが忘れがちになってしまうという問題については何一つ解決されていません.
現段階では,ちょっとだけコードが見やすくなって便利,くらいの感覚です.


もっと良い方法知ってる人いたら是非教えて下さい.