2012-11-15 17 views
8

LetPyOpenCL: differenza tra to_device e Buffer

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

Qual è la differenza tra

a_gpu = cl.Buffer(self.ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a) 

e

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

?

E qual è la differenza tra

result = numpy.empty_like(a) 
cl.enqueue_copy(self.queue, result, result_gpu) 

e

result = result_gpu.get() 

?

risposta

16

buffer sono la versione CL di malloc, mentre pyopencl.array.Array è un workalike di array numpy sul dispositivo di calcolo.

Quindi per la seconda versione della prima parte della domanda, è possibile scrivere a_gpu + 2 per ottenere un nuovo array che ha aggiunto 2 a ciascun numero nell'array, mentre nel caso dello Buffer, PyOpenCL vede solo una borsa di byte e non può eseguire alcuna operazione di questo tipo.

La seconda parte della domanda è la stessa al contrario: se si dispone di un array PyOpenCL, .get() copia i dati indietro e li converte in un array numpy (basato su host). Poiché gli array di numpy sono uno dei modi più convenienti per ottenere memoria contigua in Python, anche la seconda variante con enqueue_copy finisce in una matrice numpy, ma si noti che è possibile aver copiato questi dati in una matrice di qualsiasi dimensione (per quanto tempo in quanto è abbastanza grande) e di qualsiasi tipo - la copia viene eseguita come un sacco di byte, mentre .get() assicura che si ottengano la stessa dimensione e tipo sull'host.

Bonus: Ovviamente c'è un Buffer alla base di ogni array PyOpenCL. Puoi ottenerlo dall'attributo .data.

+4

Mi sono appena reso conto che sei l'autore di PyOpenCL. Grazie mille per PyOpenCL e per la tua risposta! – petRUShka

3

Per rispondere alla prima domanda, è possibile chiamare Buffer(hostbuf=...) con qualsiasi elemento che implementa lo buffer interface (reference). pyopencl.array.to_device(...) deve essere chiamato con ndarray (reference). ndarray implementa l'interfaccia del buffer e funziona in entrambe le posizioni. Tuttavia, solo hostbuf=... dovrebbe funzionare con, ad esempio, uno bytearray (che implementa anche l'interfaccia del buffer). Non ho confermato questo, ma sembra essere quello che suggeriscono i documenti.

riguarda la seconda domanda, io non sono sicuro di quale tipo result_gpu si suppone sia quando si chiama get() su di esso (volevi dire Buffer.get_host_array()?) In ogni caso, enqueue_copy() opere tra combinazione di Buffer, Image e host, può avere offset e regioni e può essere asincrono (con is_blocking=False) e penso che queste funzionalità siano disponibili solo in questo modo (mentre get() bloccerebbero e restituire l'intero buffer). (reference)