使用PyCUDA进行Python多处理

Bol*_*ter 16 python parallel-processing cuda multiprocessing pycuda

我有一个问题,我想拆分多个CUDA设备,但我怀疑我当前的系统架构阻碍了我;

我设置的是一个GPU类,其功能可以在GPU上执行操作(奇怪的是).这些操作都是这种风格

for iteration in range(maxval):
    result[iteration]=gpuinstance.gpufunction(arguments,iteration)
Run Code Online (Sandbox Code Playgroud)

我想象N个设备会有N个gpuinstances,但是我对多处理没有足够的了解,看看应用这个的最简单的方法,以便每个设备都被异步分配,奇怪的是我遇到的几个例子给了处理后整理结果的具体演示.

任何人都可以在这方面给我任何指示吗?

更新 感谢Kaloyan在多处理领域的指导; 如果CUDA不是特定的关键点我会标记你的回答.抱歉.

实际上,为了使用这个实现,gpuinstance类启动了CUDA设备import pycuda.autoinit但是看起来不起作用,invalid context一旦每个(正确范围的)线程遇到cuda命令就抛出错误.然后我尝试__init__在类的构造函数中手动初始化...

pycuda.driver.init()
self.mydev=pycuda.driver.Device(devid) #this is passed at instantiation of class
self.ctx=self.mydev.make_context()
self.ctx.push()    
Run Code Online (Sandbox Code Playgroud)

我的假设是在创建的gpuinstance列表和线程使用它们之间保留上下文,因此每个设备都位于自己的上下文中.

(我还实现了一个析构函数来处理pop/detach清理)

问题是,invalid context一旦线程试图触摸CUDA ,异常仍然出现.

有什么想法吗?并且感谢这么远.为在他们的答案中工作'香蕉'的人自动投票!:P

tal*_*ies 19

你需要首先在CUDA方面排好你所有的香蕉,然后考虑用Python完成这项工作的最佳方式[我知道无耻的代表妓女].

CUDA多GPU模型在4.0之前非常简单 - 每个GPU都有自己的上下文,每个上下文必须由不同的主机线程建立.所以伪代码的想法是:

  1. 应用程序启动,进程使用API​​来确定可用的GPUS数量(注意Linux中的计算模式等)
  2. 应用程序为每个GPU启动一个新的主机线程,传递GPU ID.每个线程隐式/显式调用cuCtxCreate()的等效值,传递已分配的GPU ID
  3. 利润!

在Python中,这可能看起来像这样:

import threading
from pycuda import driver

class gpuThread(threading.Thread):
    def __init__(self, gpuid):
        threading.Thread.__init__(self)
        self.ctx  = driver.Device(gpuid).make_context()
        self.device = self.ctx.get_device()

    def run(self):
        print "%s has device %s, api version %s"  \
             % (self.getName(), self.device.name(), self.ctx.get_api_version())
        # Profit!

    def join(self):
        self.ctx.detach()
        threading.Thread.join(self)

driver.init()
ngpus = driver.Device.count()
for i in range(ngpus):
    t = gpuThread(i)
    t.start()
    t.join()
Run Code Online (Sandbox Code Playgroud)

这假设在没有事先检查设备的情况下建立上下文是安全的.理想情况下,您将检查计算模式以确保尝试是安全的,然后在设备繁忙时使用异常处理程序.但希望这给出了基本的想法.