我有一个结构,看起来像这个
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
请告诉我我的代码出了什么问题,以及如何正确处理?提前谢谢。
问题是在同一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);
}
}
【免责声明:在浏览器中编写,从未编译,使用风险自负】
显然,您需要定义一个析构函数来防止内存泄漏。还有其他的可能性,我将把它留给读者练习。