2012-11-15 263 views
8

之間的差異讓Pyopencl:to_device和緩衝區

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() 

之間的區別?

回答

16

緩衝區是CL的版本malloc,而pyopencl.array.Array是計算設備上numpy陣列的工作區。

因此,對於問題第一部分的第二個版本,您可以編寫a_gpu + 2以獲得一個新陣列,其中每個數字添加了2個陣列,而在Buffer的情況下,PyOpenCL只能看到一個包的字節並且不能執行任何這樣的操作。

你的問題的第二部分是相反的:如果你有一個PyOpenCL陣列,.get()將數據複製回來並將它轉換成一個(基於主機的)numpy數組。由於numpy數組是用Python獲取連續內存的更方便的方法之一,因此enqueue_copy的第二個變體也以numpy數組結尾 - 但請注意,您可以將此數據複製到任意大小的數組中(只要因爲它足夠大)以及任何類型 - 複製是作爲一包字節執行的,而.get()可確保您在主機上獲得相同的大小和類型。

獎金事實:當然每個PyOpenCL數組都有一個Buffer。你可以從.data屬性中獲得它。

+4

我剛剛意識到你是PyOpenCL的作者。非常感謝PyOpenCL和您的答案! – petRUShka

3

要回答第一個問題,可以使用實現buffer interfacereference)的任何東西來調用Buffer(hostbuf=...)。必須使用ndarrayreference)調用pyopencl.array.to_device(...)ndarray實現緩衝區接口並在任何地方工作。但是,只有hostbuf=...預計可以與例如bytearray(它也實現緩衝接口)一起使用。我沒有證實這一點,但它似乎是文件的建議。

關於第二個問題,我不知道應該是什麼類型result_gpu是,當你調用它的get()(你的意思是Buffer.get_host_array()?)在任何情況下,BufferImagehost組合之間enqueue_copy()作品,可以有偏移和區域,並且可以是異步的(使用is_blocking=False),我認爲這些功能只能以這種方式使用(而get()會阻塞並返回整個緩衝區)。 (reference