我在一个项目中,我将计算任务分配给多个python进程,每个进程都与它自己的CUDA设备相关。在
生成子流程时,我使用以下代码:
import pycuda.driver as cuda
class ComputeServer(object):
def _init_workers(self):
self.workers = []
cuda.init()
for device_id in range(cuda.Device.count()):
print "initializing device {}".format(device_id)
worker = CudaWorker(device_id)
worker.start()
self.workers.append(worker)
同事在另一个文件中的定义如下:
^{pr2}$当我在Windows7或Linux上运行这段代码时,我没有问题。在装有OSX 10.8.2、Cuda 5.0和PyCuda 2012.1的MacBook Pro上运行代码时,出现以下错误:
Process CudaWorker-1:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/Users/tombnorwood/pymodules/computeserver/worker.py", line 32, in run
self._init_cuda_context()
File "/Users/tombnorwood/pymodules/computeserver/worker.py", line 38, in _init_cuda_context
cuda.init()
RuntimeError: cuInit failed: no device
在我的Mac上运行PyCuda脚本而不分叉新进程,我没有问题。我只有在生成新进程时才会遇到这个问题。在
以前有人遇到过这个问题吗?在
根据我的经验,这只是一个有根据的猜测,但是我怀疑CUDA(或者可能是PyCuda)的OS X实现依赖于一些在
fork
之后无法安全使用的api,而linux实现则没有。*因为multiprocessing
的POSIX实现使用fork
而没有exec
来创建子进程,因此可以解释为什么它在OSX上失败,而不是在linux上。(在Windows上,是没有fork
,只是一个spawn
的等价物,所以这不是问题。)最简单的解决方案是删除}并完成它。或者,您可以考虑为
multiprocessing
。如果CUDA和PyCUDA是线程安全的(我不知道它们是否是线程安全的),并且您的代码不是CPU绑定的(只是GPU绑定的),那么您可以直接插入threading.Thread
来代替{multiprocessing
提供类似api的其他并行处理库之一。(有些人使用pp
仅仅因为它总是exec
s…)然而,很容易将
multiprocessing
修改成exec
/spawn
一个新的Python解释器,然后执行Windows风格而不是POSIX风格的所有操作。(使每个用例都正确是很困难的,但是正确地获得一个特定的用例是很容易的。)或者,如果你看一下bug #8713,一般来说,有一些工作要做。还有工作补丁。这些贴片是3.3版的,不是2.7版的,所以你可能需要做一些按摩,但不应该太多。因此,只需},并添加适当的调用来选择spawn/fork+exec/无论最新补丁中调用的模式是什么,然后再做其他操作。在
cp $MY_PYTHON_LIB/multiprocessing.py $MY_PROJECT_DIR/mymultiprocessing.py
,对其进行修补,使用mymultiprocessing
代替{*OP说他怀疑同样的事情,所以我可能不需要向他解释这一点,但是为了将来的读者:这不是关于达尔文和其他Unix之间的区别,而是关于苹果发布了很多非Unix-y的中级库,比如核心基础.framework, 加速.framework, 等等,使用不安全的fork后功能(或者只是断言在fork之后没有使用它们,因为苹果不想在他们说“asto10.X,Foo.框架叉后安全”)。另外,如果你比较一下OSX和linux处理图形和其他硬件的方式,在OSX中每个进程用户空间中都有更多的中级用户空间
相关问题 更多 >
编程相关推荐