我会尽力说清楚;
我有两节课; GPU(Object)
,用于对GPU功能的一般访问,multifunc(threading.Thread)
用于特定功能,我正在尝试使用多设备。 GPU
包含所有后续用例所需的大部分“首次”处理,因此从multifunc
调用GPU
,其self
实例作为__init__
传递参数(以及通常的队列等)。
不幸的是,multifunc
匆匆忙忙:
File "/home/bolster/workspace/project/gpu.py", line 438, in run
prepare(d_A,d_B,d_XTG,offset,grid=N_grid,block=N_block)
File "/usr/local/lib/python2.7/dist-packages/pycuda-0.94.2-py2.7-linux-x86_64.egg/pycuda/driver.py", line 158, in function_call
func.set_block_shape(*block)
LogicError: cuFuncSetBlockShape failed: invalid handle
第一个停靠点当然是块尺寸,但是它们在范围内(即使我强制block=(1,1,1)
也是相同的行为,同样是网格。
基本上,在multifunc
内,所有常见的CUDA memalloc等函数都可以正常工作(意味着它不是上下文问题)所以问题必须是内核函数本身的SourceModule
。
我有一个内核模板,其中包含我的所有CUDA代码,这些代码都是文件范围的,并且在jinja2
初始化中使用GPU
完成了模板化。无论该模板化对象是否转换为SourceModule
中的GPU
对象并传递给multifunc
,或者如果它在multifunc
中转换,同样的事情都会发生。
谷歌在这个特定问题上基本没用,但是在堆栈之后,我假设被引用的Invalid Handle
是内核函数句柄,而不是块大小的任何奇怪的事情。
我知道这是一个非常严峻的情况,但我确信有人可以看到我错过的问题。
答案 0 :(得分:3)
原因是上下文亲和力。每个CUDA函数实例都与上下文相关联,并且它们不可移植(同样适用于内存分配和纹理引用)。因此,每个上下文必须单独加载函数实例,然后使用该加载操作返回的函数句柄。
如果您根本不使用元编程,您可能会发现将CUDA代码编译为cubin文件更简单,然后使用driver.module_from_file
将所需的函数从cubin加载到每个上下文。直接从我的一些生产代码中切割和粘贴:
# Context establishment
try:
if (autoinit):
import pycuda.autoinit
self.context = None
self.device = pycuda.autoinit.device
self.computecc = self.device.compute_capability()
else:
driver.init()
self.context = tools.make_default_context()
self.device = self.context.get_device()
self.computecc = self.device.compute_capability()
# GPU code initialization
# load pre compiled CUDA code from cubin file
# Select the cubin based on the supplied dtype
# cubin names contain C++ mangling because of
# templating. Ugly but no easy way around it
if self.computecc == (1,3):
self.fimcubin = "fim_sm13.cubin"
elif self.computecc[0] == 2:
self.fimcubin = "fim_sm20.cubin"
else:
raise NotImplementedError("GPU architecture not supported")
fimmod = driver.module_from_file(self.fimcubin)
IterateName32 = "_Z10fimIterateIfLj8EEvPKT_PKiPS0_PiS0_S0_S0_jjji"
IterateName64 = "_Z10fimIterateIdLj8EEvPKT_PKiPS0_PiS0_S0_S0_jjji"
if (self.dtype == np.float32):
IterateName = IterateName32
elif (self.dtype == np.float64):
IterateName = IterateName64
else:
raise TypeError
self.fimIterate = fimmod.get_function(IterateName)
except ImportError:
warn("Could not initialise CUDA context")
答案 1 :(得分:0)
典型;一旦我写出问题,我就会解决这个问题。
问题是让SourceModule在活动上下文之外运行。为了解决这个问题,我将SourceModule调用移动到了cuda上下文设置下面的线程中的run函数。
暂时搁置一段时间因为我确信其他人有更好的解释!