nishio-dens's diary

Railsとかプログラミング関連の備忘録

CUDAでのカーネル関数のタイムアウト

LinuxでのXWindowやWindowsを使っている場合,CUDAで一つのカーネル関数が一定時間以上の処理を行うとプログラムが勝手に終了されてしまう.
Linux(Ubuntu10.04にて確認)の場合,カーネル関数が10秒以上の処理を行うと,プログラムが正常に動かなくなってしまう.Windowsの場合は5秒以上だそうだが試したことはない.あまり長い時間動かしてると,最悪コンピュータ自体が止まってしまい再起動しないといけなくなる.どうやらウォッチドッグタイマ(Watchdog timer)が働いてしまい,GPUが一定時間以上ビジーになると,プログラムを勝手に止めてしまうそうだ.
解決策を色々探してみたが,結局XWindowを切ってプログラムを実行するか,グラボを2枚以上挿すしかないそうだ.ちなみに,Ubuntuの場合,XWindowを終了するには,ターミナルにて

sudo /etc/init.d/gdm stop

を入力すればよい.

CUDAのプログラム内にてカーネル関数が正常に終了したかどうかを確認するには,CUT_CHECK_ERROR関数を使えばよい.試しに次のようなプログラムでカーネル関数のタイムアウトが起こるか実験してみた.

#include <stdio.h>
#include <cutil.h>

//バッファにスレッドIDを書きだすだけのプログラム
__global__ void timeoutTest(int size, int* output_buffer)
{
  int i = threadIdx.x;
  int j=0;
  int k=0;
  int num=100000;

  //繰り返しの回数を上げるとタイムアウトが起こる
  for(j=0; j < num; j++) {
    for(k=0; k < num; k++) {
      output_buffer[i] = i;
    }
  }
}

int main()
{
  int* output_buffer;
  int* buffer;

  int threadNum = 512;
  int i;
  
  cudaMalloc(&output_buffer, threadNum * sizeof(int));
  buffer = (int*)malloc(threadNum * sizeof(int));

  //タイムアウトのテスト
  timeoutTest<<<1,threadNum>>>(threadNum, output_buffer);
  cudaMemcpy(buffer, output_buffer, threadNum * sizeof(int), cudaMemcpyDeviceToHost);

  //カーネル関数実行でエラーが起こっていないか
  CUT_CHECK_ERROR("Kernel Error.\n");

  cudaFree(output_buffer);

  //バッファの内容を出力
  for(i=0; i < threadNum; i++) {
    printf("%d=%d\n", i, buffer[i]);
  }
  free(buffer);
  return 0;
}

CUT_CHECK_ERROR関数を呼び出すには,cutil.hをインクルードしなければならないことをお忘れなく.上記のコードを実行してみたらタイムアウトが見事に起こる.

Cuda error: Kernel Error.
in file 'timeout.cu' in line 36 : unspecified launch failure.

実行結果はこんな感じ.カーネル関数を呼び出したあとは,正しく処理が終了しているかどうかをチェックするためにCUT_CHECK_ERROR関数を呼び出した方がよい.