Ricerca…


introduzione

Questo argomento evidenzia diversi modi per inserire dati da qualche parte dove il dispositivo può accedervi.

Leggere un array

Per leggere un array dal dispositivo di nuovo all'host, si effettua una chiamata

clEnqueueReadBuffer($queue, $memobj, $blocking, $offset, $size, $target, 0, null, null);

$ Queue è CommandQueue che è stato utilizzato per allocare la memoria sul dispositivo. $ Memobj contiene l'indirizzo nella memoria del dispositivo, $ offset e $ size definiscono ulteriormente da dove e quanti dati vengono copiati. $ Target è un puntatore alla memoria dell'host in cui verranno archiviati i dati. L'obiettivo $ deve essere allocato e avere una dimensione appropriata.

Leggendo una Texture

Leggere un'immagine è quasi come leggere un array. L'unica differenza è che la dimensione e l'offset devono essere tridimensionali.

clEnqueueReadImage($queue, $memobj, $blocking, $offset, $size, $stride, $slice_pitch, $target, 0, null, null);

$ Stride definisce quanti byte ha una riga. Normalmente questo è solo larghezza * (byte per pixel), ma qualcuno potrebbe volerlo cambiare per allineare i dati con i banchi di memoria. Lo stesso vale per $ slice_pitch, solo che questo valore è per la terza dimensione.

Scrivere una trama 2D

Per copiare una texture sul dispositivo sono necessari due passaggi

  1. Assegna la memoria sul dispositivo
  2. Copia l'immagine sul dispositivo
  _mem = clCreateImage2D($context, $mem_flags, $image_format, $width, $height, $stride, $source, &err);

I $ mem_flags definiscono come viene allocata la memoria. Può essere solo di sola lettura, solo scrittura o entrambi. Inoltre è possibile definire dove e come viene allocata la memoria. $ width, $ height e $ stride sono piuttosto auto-esplicativi.

Se i tuoi mem_flags copiano i dati, hai finito. Se vuoi farlo manualmente in un secondo momento, dovrai chiamare un'altra funzione quando sei pronto.

err = clEnqueueWriteImage($queue, _mem, $blocking, $offset, $size, $stride, $slice_pitch, $source, 0, null, null);

$ Offset e $ size definiscono l'area dell'immagine che si desidera copiare nella memoria di destinazione. $ Stride definisce quanti byte ha una riga. Normalmente questo è solo larghezza * (byte per pixel), ma qualcuno potrebbe volerlo cambiare per allineare i dati con i banchi di memoria. Lo stesso vale per $ slice_pitch, solo che questo valore è per la terza dimensione. Sia $ stride che $ slice_pitch devono corrispondere ai dati di input.

Bandiere di memoria

Quando assegni alla memoria hai la possibilità di scegliere tra diverse modalità:

  • Memoria di sola lettura
  • Scrivi solo memoria
  • Leggi / scrivi memoria

La memoria di sola lettura è allocata nella regione di memoria __constant, mentre gli altri due sono allocati nella normale regione __global.

Oltre all'accessibilità, puoi definire dove è allocata la tua memoria.

  • Non specificato: la memoria viene allocata nella memoria del dispositivo come ci si aspetterebbe. Il puntatore $ source può essere impostato su null.
  • CL_MEM_USE_HOST_PTR: indica al dispositivo che i dati si trovano nella RAM di sistema e non devono essere spostati. Invece i dati sono manipolati direttamente nella ram.
  • CL_MEM_COPY_HOST_PTR: indica al dispositivo di copiare tutti i valori all'indirizzo specificato nella memoria del dispositivo o, utilizzando CL_MEM_ALLOC_HOST_PTR, in un'area di memoria separata nella ram di sistema.
  • CL_MEM_ALLOC_HOST_PTR: indica al dispositivo di allocare spazio nella ram del sistema. Se usato come unico parametro, il puntatore $ source può essere impostato su null.

In termini di velocità, l'accesso alla memoria globale del dispositivo è il più veloce. Ma devi anche chiamarlo due volte per copiare i dati. L'utilizzo del puntatore Host è il più lento, mentre Alloc_host_ptr offre una velocità maggiore.

Quando si utilizza use_host_ptr, il dispositivo fa esattamente questo: usa i dati nella ram del sistema, che naturalmente viene cercata dal sistema operativo. Quindi ogni chiamata di memoria deve passare attraverso la CPU per gestire potenziali pagefaults. Quando i dati sono disponibili, la cpu lo copia nella memoria bloccata e lo passa al controller DMA utilizzando preziosi cicli di clock della CPU. Al contrario, alloc_host_ptr alloca la memoria bloccata nella ram del sistema. Questa memoria è posizionata all'esterno del meccanismo di paginewap e pertanto ha una disponibilità garantita. Pertanto, il dispositivo può saltare completamente la cpu quando accede alla RAM del sistema e utilizza DMA per copiare rapidamente i dati sul dispositivo.

Scrivere un array

La scrittura di un array consiste di due passaggi:

  1. Allocazione della memoria
  2. Copia dei dati

Per allocare la memoria, una semplice chiamata a

_mem = clCreateBuffer($queue, $mem_flags, $size, $host_ptr, &err);

è abbastanza. Se hai deciso di copiare il puntatore dell'host tramite mem_flags, hai finito. Altrimenti puoi copiare i dati quando vuoi

err = clEnqueueWriteBuffer($queue, _mem, $blocking, $offset, $size, $source, 0, null, null);


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow