PyCuda /多处理问题在OS X 10.8 [英] PyCuda / Multiprocessing Issue on OS X 10.8

查看:325
本文介绍了PyCuda /多处理问题在OS X 10.8的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个项目,其中我将计算任务分配给每个与其自己的CUDA设备相关联的多个python进程。



当生成子进程时,以下代码:

  import pycuda.driver as cuda 

类ComputeServer(object):
def _init_workers(self):
self.workers = []
cuda.init()
在device_id范围内(cuda.Device.count()):
print initialize device {}。format(device_id)
worker = CudaWorker(device_id)
worker.start()
self.workers.append(worker)



CudaWorker在另一个文件中定义如下:

 来自多进程导入进程
import pycuda.driver as cuda

类CudaWorker(进程):
def __init __(self,device_id):
进程。 __init __(self)
self.device_id = device_id

def run(self):
self._init_cuda_context()
while True:
#这里

def _init_cuda_context(self):
#以下行失败
cuda.init()
device = cuda.Device(self.device_id)
self.cuda_context = device.make_context()



当在Windows 7或Linux上运行此代码时,我没有问题。当运行代码在我的MacBook Pro与OSX 10.8.2,Cuda 5.0和PyCuda 2012.1我得到以下错误:

 过程CudaWorker-1:
Traceback(最近调用最后):
文件/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py,行258,in _bootstrap
self.run()
文件/Users/tombnorwood/pymodules/computeserver/worker.py,第32行,在运行
self._init_cuda_context()
文件/Users/tombnorwood/pymodules/computeserver/worker.py,第38行,位于_init_cuda_context
cuda.init()
RuntimeError:cuInit failed:no device

我没有问题运行PyCuda脚本,而没有分支在我的Mac上的新进程。



有人在遇到这个问题吗?解决方案

这真的只是一个有根据的猜测,基于我的经验,但我怀疑CUDA(或可能是PyCuda)的OS X实现依赖于一些API,不能安全地使用<$因为 multiprocessing 的POSIX实现使用 fork code>没有 exec 来创建子进程,这将解释为什么它在OS X而不是Linux上失败。 (在Windows上, fork ,只是一个 spawn 不是问题。)



最简单的解决方案是删除 multiprocessing 。如果CUDA和PyCUDA是线程安全的(我不知道它们是否),并且你的代码不是CPU限制的(只是GPU绑定),你可以只是放入线程。线程代替 multiprocessing.Process ,并使用它。或者,您可以考虑提供类似于 multiprocessing 的API的其他并行处理库之一。 (有几个人使用 pp 只是因为它总是 exec s ...)



但是,很容易将多处理改为 exec / spawn 一个新的Python解释器,然后做一切Windows风格而不是POSIX风格。 (获取每个案例是困难的,但获得一个特定的用例是很容易。)



或者,如果你看 bug#8713 ,有一些工作正在进行这项工作一般。还有工作补丁。这些补丁是3.3,而不是2.7,所以你可能需要一点点按摩,但它不应该是很多。因此,只需 cp $ MY_PYTHON_LIB / multiprocessing.py $ MY_PROJECT_DIR / mymultiprocessing.py ,修补它,使用 mymultiprocessing multiprocessing ,并添加相应的调用pick spawn / fork + exec /无论在执行任何操作之前在最新补丁中调用的模式。






* OP说他怀疑同样的事情,所以我可能不需要向他解释,但是对于未来的读者:关于达尔文和其他Unix之间的区别,但是关于这样一个事实,苹果发运了很多非Unix中间级库,如CoreFoundation.framework,Accelerate.framework等,使用不安全的后叉功能(或只是断言他们不是在叉子后被使用,因为苹果不想进行严格的测试,他们可以说作为10.X,Foo.framework是安全的叉后)。此外,如果你比较OS X和linux处理图形和其他硬件的方式,在OS X中有更多的中间层的每个进程的用户空间。


I'm working on a project where I distribute compute tasks to multiple python Processes each associated with its own CUDA device.

When spawning the subprocesses, I use the following code:

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)

The CudaWorker is defined in another file as follows:

from multiprocessing import Process
import pycuda.driver as cuda

class CudaWorker(Process):
    def __init__(self, device_id):
        Process.__init__(self)
        self.device_id = device_id

    def run(self):
        self._init_cuda_context()
        while True:
            # process requests here

    def _init_cuda_context(self):
        # the following line fails
        cuda.init()
        device = cuda.Device(self.device_id)
        self.cuda_context = device.make_context()

When I run this code on Windows 7 or Linux, I have no issues. When running the code on my MacBook Pro with OSX 10.8.2, Cuda 5.0, and PyCuda 2012.1 I get the following error:

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

I have no issues running PyCuda scripts without forking new processes on my Mac. I only get this issue when spawning a new Process.

Has anyone run into this issue before?

解决方案

This is really just an educated guess based on my experienced, but I suspect that the OS X implementation of CUDA (or possibly PyCuda) relies on some APIs that can't be used safely after fork, while the linux implementation does not.* Since the POSIX implementation of multiprocessing uses fork without exec to create child processes, this would explain why it fails on OS X but not linux. (And on Windows, there is no fork, just a spawn equivalent, so this isn't an issue.)

The simplest solution would be to drop multiprocessing. If CUDA and PyCUDA are thread-safe (I don't know if they are), and your code is not CPU-bound (just GPU-bound), you might be able to just drop in threading.Thread in place of multiprocessing.Process and be done with it. Or you could consider one of the other parallel-processing libraries that provide similar APIs to multiprocessing. (There are a few people who use pp only because it always execs…)

However, it's pretty easy to hack up multiprocessing to exec/spawn a new Python interpreter and then do everything Windows-style instead of POSIX-style. (Getting every case right is difficult, but getting one specific use case right is easy.)

Or, if you look at bug #8713, there's some work being done on making this work right in general. And there are working patches. Those patches are for 3.3, not 2.7, so you'd probably need a bit of massaging, but it shouldn't be very much. So, just cp $MY_PYTHON_LIB/multiprocessing.py $MY_PROJECT_DIR/mymultiprocessing.py, patch it, use mymultiprocessing in place of multiprocessing, and add the appropriate call to pick spawn/fork+exec/whatever the mode is called in the latest patch before you do anything else.


* The OP says he suspected the same thing, so I probably don't need to explain this to him, but for future readers: It's not about a difference between Darwin and other Unixes, but about the fact that Apple ships a lot of non-Unix-y mid-level libraries like CoreFoundation.framework, Accelerate.framework, etc. that use unsafe-after-fork functionality (or just assert that they're not being used after a fork because Apple doesn't want to put in the rigorous testing that would be warranted before they could say "as of 10.X, Foo.framework is safe after fork"). Also, if you compare the way OS X and linux deal with graphics and other hardware, there's a lot more mid-level in-each-process-userspace going on in OS X.

这篇关于PyCuda /多处理问题在OS X 10.8的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆