让
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()
答案 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 interface(reference)的任何内容调用Buffer(hostbuf=...)
。必须使用pyopencl.array.to_device(...)
(reference)调用ndarray
。 ndarray
实现缓冲区接口并在任何一个地方工作。但是,只有hostbuf=...
可以使用例如bytearray
(也实现缓冲区接口)。我没有证实这一点,但似乎是文档的建议。
关于第二个问题,当您致电result_gpu
时,我不确定get()
应该是什么类型(您的意思是Buffer.get_host_array()
?)无论如何,{{ 1}}在enqueue_copy()
,Buffer
和Image
的组合之间工作,可以有偏移和区域,并且可以是异步的(使用host
),我认为这些功能是只有那种方式可用(而is_blocking=False
将阻塞并返回整个缓冲区)。 (reference)