0

私はこのような構造体を持っています

struct LstmLayer {
  int deviceId;
  thrust::device_vector <real_t> W;
  thrust::device_vector <real_t> gradW;

  LstmLayer() : deviceId(0) {}

  LstmLayer(int __deviceId__) : deviceId(__deviceId__) {}

  void setDevice(int __deviceId__) { deviceId = __deviceId__; }

  void init(bool initParams) {
    W.resize(4*lstmSize * 2*lstmSize);
    gradW.resize(4*lstmSize * 2*lstmSize);

    if (initParams) GPU_Random_Vector(W);
  }
}

LstmLayerここで、各要素が異なる GPU デバイス上にある の配列を初期化したいと考えています。私は次のようにします

  struct LstmLayer lstmLayers[MAX_NUM_LSTM_LAYERS];

  for (int i = 0; i < numLstmLayers; ++i) {
    CUDA_SAFE_CALL(cudaSetDevice(i));
    lstmLayers[i].setDevice(i);
    lstmLayers[i].init(true);
  }

このプログラムを実行すると、次のエラーが発生します

terminate called after throwing an instance of 'thrust::system::system_error'
  what():  driver shutting down

私のコードの何が問題なのか、それを正しく行う方法を教えてください。よろしくお願いします。

4

1 に答える 1

5

問題は、同じ CUDA GPU コンテキストですべてのベクトルをインスタンス化してから、それらを別のコンテキストで使用しようとしていることです。device_vectorこれは、構造体の配列を定義するときに、それぞれの既定のコンストラクターが呼び出されるために発生します。コードに注釈を付けるには:

struct LstmLayer lstmLayers[MAX_NUM_LSTM_LAYERS]; // default constructor for each device vector called here in one GPU context.

for (int i = 0; i < numLstmLayers; ++i) {
    CUDA_SAFE_CALL(cudaSetDevice(i));
    lstmLayers[i].setDevice(i);
    lstmLayers[i].init(true); // Error here, you changed to a different device and called resize
}

解決策は、おそらくデバイス ベクターをポインターとして再定義し、initメソッドでそれらのコンストラクターを明示的に呼び出すことです。これにはさまざまな方法があります。たとえば、次のようになります。

 struct LstmLayer {
  int deviceId;
  thrust::device_vector <real_t>  * W;
  thrust::device_vector <real_t> * gradW;

  LstmLayer() : deviceId(0) {}

  LstmLayer(int __deviceId__) : deviceId(__deviceId__) {}

  void setDevice(int __deviceId__) { deviceId = __deviceId__; }

  void init(bool initParams) {
    W = new thrust::device_vector<real_t>(4*lstmSize * 2*lstmSize);
    gradW = new thrust::device_vector<real_t>(4*lstmSize * 2*lstmSize);

    if (initParams) GPU_Random_Vector(W);
  }
}

[免責事項: ブラウザーで記述され、コンパイルされていません。自己責任で使用してください]

明らかに、メモリ リークを防ぐためにデストラクタを定義する必要があります。他にも可能性はありますが、それは読者の課題として残しておきます。

于 2015-06-24T18:18:53.480 に答える