Инициализировать структуру на разных графических процессорах

У меня есть структура, которая выглядит так

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с каждым элементом на другом устройстве графического процессора. Я делаю это следующим образом

  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

Подскажите пожалуйста что не так с моим кодом и как это сделать правильно? Заранее благодарю.

0

Решение

Проблема в том, что вы создаете все векторы в одном и том же контексте графического процессора CUDA, а затем пытаетесь использовать их в другом контексте. Это происходит потому, что конструктор по умолчанию для каждого 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);
}
}
[заявление об отказе: написано в браузере, никогда не компилируется, используйте на свой страх и риск]

Очевидно, вам нужно определить деструктор для предотвращения утечек памяти. Есть и другие возможности, я оставлю это в качестве упражнения для читателя.

5

Другие решения


По вопросам рекламы [email protected]