一个线程的Device(gpu)设置独立于同一进程中的其他线程。查看此以获取更多详细信息。
我还没有找到在 Theano 中为当前线程设置设备的方法。我使用过时cuda_ndarray
的后端,没有办法做到这一点,但我不知道gpuarray
后端是否有办法做到这一点。
我做了一些解决方法:
import numpy as np
import theano
from theano import Apply
from theano import tensor as T
from theano.scalar import Scalar
from theano.sandbox.cuda import GpuOp, nvcc_compiler
class SetGpu(GpuOp):
'''
Set device(gpu) for current thread.
'''
def c_compiler(self):
return nvcc_compiler.NVCC_compiler
def make_node(self, gpu_id):
dummy_out = Scalar("int32")()
return Apply(self, [gpu_id], [dummy_out])
def __str__(self):
return "SetGpu"
def c_support_code_apply(self, node, nodename):
return ""
def c_code(self, node, nodename, inps, outs, sub):
gpu_id, = inps
dummy_out, = outs
return """
int _gpu_id = *((int*)PyArray_DATA(%(gpu_id)s));
%(dummy_out)s = _gpu_id;
cudaError_t err = cudaSetDevice(_gpu_id);
if(err != cudaSuccess){
PyErr_Format(PyExc_RuntimeError, "Cuda err:\\"%%s\\" when calling cudaSetDevice(%%d).", cudaGetErrorString(err), _gpu_id);
return 0;
}
""" % locals()
def set_gpu(gpu_id):
if not hasattr(set_gpu, "f"):
set_gpu_op = SetGpu()
gpu_id_var = T.iscalar()
dummy_out = set_gpu_op(gpu_id_var)
set_gpu.f = theano.function([gpu_id_var], [dummy_out])
_dummy_out = set_gpu.f(gpu_id)
if __name__ == "__main__":
def test():
set_gpu(5)
print "Test thread is using gpu %d." % theano.sandbox.cuda.active_device_number()
print "Main thread is using gpu %d." % theano.sandbox.cuda.active_device_number()
from threading import Thread
thread = Thread(target=test)
thread.start()
thread.join()
所以我们称这个文件为 set_gpu.py
这是我运行它的内容:
python set_gpu.py
WARNING (theano.sandbox.cuda): The cuda backend is deprecated and will be removed in the next release (v0.10). Please switch to the gpuarray backend. You can get more information about how to switch at this URL:
https://github.com/Theano/Theano/wiki/Converting-to-the-new-gpu-back-end%28gpuarray%29
Using gpu device 0: Tesla K80 (CNMeM is enabled with initial size: 95.0% of memory, cuDNN 5110)
Main thread is using gpu 0.
Test thread is using gpu 5.