PyCUDA + Threading =内核调用无效的句柄
我会尽力澄清这一点;
我有两节课。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
发生了在相同事物中进行了转换的情况。
Google在这个特定问题上基本上没有用,但是在堆栈之后,我假设Invalid
Handle
被引用的是内核函数句柄,而不是块尺寸方面发生的任何奇怪的事情。
我知道这是一个非常极端的情况,但是我确信有人可以看到我错过的问题。
-
原因是上下文关联。每个CUDA函数实例都与上下文相关联,并且它们不是可移植的(这适用于内存分配和纹理引用)。因此,每个上下文必须分别加载函数实例,然后使用该加载操作返回的函数句柄。
如果根本不使用元编程,则可能会发现将CUDA代码编译为cubin文件,然后使用来将所需的功能从cubin加载到每个上下文会更简单
driver.module_from_file
。直接从我的一些生产代码中剪切和粘贴:# 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")