Pyopencl:to_device和Buffer之间的区别

时间:2012-11-15 11:18:42

标签: python numpy opencl pyopencl

import pyopencl as cl
import pyopencl.array as cl_array
import numpy
a = numpy.random.rand(50000).astype(numpy.float32)
mf = cl.mem_flags

之间有什么区别
a_gpu = cl.Buffer(self.ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a)

a_gpu = cl_array.to_device(self.ctx, self.queue, a)

之间有什么区别
result =  numpy.empty_like(a)
cl.enqueue_copy(self.queue, result, result_gpu)

result = result_gpu.get()

2 个答案:

答案 0 :(得分:18)

缓冲区是CL的malloc版本,而pyopencl.array.Array是计算设备上numpy数组的工作方式。

因此,对于问题第一部分的第二个版本,您可以编写a_gpu + 2来获取一个新数组,该数组在数组中的每个数字中都添加了2个,而在{{1}的情况下},PyOpenCL只看到一包字节,不能执行任何此类操作。

你的问题的第二部分是相反的:如果你有一个PyOpenCL数组,Buffer将数据复制回来并将其转换为(基于主机的)numpy数组。由于numpy数组是在Python中获取连续内存的更方便的方法之一,因此.get()的第二个变体也会以一个numpy数组结束 - 但请注意,您可以将此数据复制到任何数组中大小(只要它足够大)和任何类型 - 副本作为一个字节包执行,而enqueue_copy确保您在主机上获得相同的大小和类型。

Bonus事实:每个PyOpenCL数组当然都有一个Buffer。您可以从.get()属性中获取它。

答案 1 :(得分:3)

要回答第一个问题,可以使用实现buffer interfacereference)的任何内容调用Buffer(hostbuf=...)。必须使用pyopencl.array.to_device(...)reference)调用ndarrayndarray实现缓冲区接口并在任何一个地方工作。但是,只有hostbuf=...可以使用例如bytearray(也实现缓冲区接口)。我没有证实这一点,但似乎是文档的建议。

关于第二个问题,当您致电result_gpu时,我不确定get()应该是什么类型(您的意思是Buffer.get_host_array()?)无论如何,{{ 1}}在enqueue_copy()BufferImage的组合之间工作,可以有偏移和区域,并且可以是异步的(使用host),我认为这些功能是只有那种方式可用(而is_blocking=False将阻塞并返回整个缓冲区)。 (reference