CLBufferWrite

Scrive nel buffer OpenCL e restituisce il numero di elementi scritti.

uint  CLBufferWrite(
   int          buffer,                    // Un handle per un buffer OpenCL
   const void&  data[],                    // Un array di valori
   uint         buffer_offset=0,           // Un offset nel buffer OpenCL in bytes, 0 per default
   uint         data_offset=0,             // Un offset negli elementi dell' array, 0 per default
   uint         data_count=WHOLE_ARRAY     // Il numero di valori dall'array per la scrittura; l'intero array di default
   );

Ci sono anche versioni per la gestione di matrici e vettori.

Scrive i valori dalla matrice nel buffer e restituisce true in caso di esito positivo.

uint  CLBufferWrite(
   int           buffer,                    // un handle al buffer OpenCL
   uint          buffer_offset,             // uno scostamento nel buffer OpenCL in byte
   matrix<T>     &mat                       /i valori della matrice per la scrittura nel buffer
   );

Scrive i valori dal vettore nel buffer e restituisce true in caso di esito positivo.

uint  CLBufferWrite(
   int           buffer,                    // un handle al buffer OpenCL
   uint          buffer_offset,             // uno scostamento nel buffer OpenCL in byte
   vector<T>     &vec                       // i valori del vettore per la scrittura nel buffer
   );

Parametri

buffer

[in]  Un handle di un buffer OpenCL.

data[]

[in] Un array di valori che dovrebbero essere scritti nel buffer OpenCL. Passato per riferimento.

buffer_offset

[in] Un offset nel buffer OpenCL in byte, da cui inizia la scrittura. Per default, la scrittura inizia dall'inizio del buffer.

data_offset

[in] L'indice del primo elemento dell'array, a partire dal quale i valori dell'array sono scritti nel buffer OpenCL. Per impostazione predefinita, vengono presi i valori sin dall'inizio dell'array.

data_count

[in] Il numero di valori che devono essere scritti. Tutti i valori dell'array, di default.

mat

[out]  La matrice per la lettura dei dati dal buffer può essere uno qualsiasi dei tre tipi: matrix, matrixf o matrixc.

vec

[out]  Il vettore per la lettura dei dati dal buffer può essere di uno qualsiasi dei tre tipi — vector, vectorf or vectorc.

Valore restituito

Il numero di elementi scritti. 0 viene restituito in caso di errore. Per ulteriori informazioni sull'errore, utilizzare la funzione GetLastError().

true se una matrice o un vettore vengono gestiti correttamente, altrimenti false.

Nota

Per array uni-dimensionali, il numero dell'elemento, con cui la lettura dei dati di scrittura in un inizio di buffer OpenCL, viene calcolata tenendo conto delle flags AS_SERIES.

Un array di due o più dimensioni è presentata come uni-dimensionale. In questo caso, data_offset è il numero di elementi che devono essere saltati nella presentazione, non il numero di elementi nella prima dimensione.

Esempio di moltiplicazione di matrici utilizzando il metodo MatMul e calcolo parallelo in OpenCL

#define M       3000      // il numero di righe nella prima matrice
#define K       2000      //il numero di colonne nella prima matrice è uguale al numero di righe nella seconda 
#define N       3000      //il numero di colonne nella seconda matrice
 
//+------------------------------------------------------------------+
const string clSrc=
  "#define N     "+IntegerToString(N)+"                              \r\n"
  "#define K     "+IntegerToString(K)+"                              \r\n"
  "                                                                  \r\n"
  "__kernel void matricesMul( __global float *in1,                   \r\n"
  "                           __global float *in2,                   \r\n"
  "                           __global float *out  )                 \r\n"
  "{                                                                 \r\n"
  "  int m = get_global_id( 0 );                                     \r\n"
  "  int n = get_global_id( 1 );                                     \r\n"
  "  float sum = 0.0;                                                \r\n"
  "  for( int k = 0; k < K; k ++ )                                   \r\n"
  "     sum += in1[ m * K + k ] * in2[ k * N + n ];                  \r\n"
  "  out[ m * N + n ] = sum;                                         \r\n"
  "}                                                                 \r\n";
//+------------------------------------------------------------------+
//| Programma Script funzione start                                  |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- inizializza il generatore di numeri casuali
  MathSrand((int)TimeCurrent());
//---riempie le matrici di una certa dimensione con valori casuali
  matrixf mat1(MKMatrixRandom) ;    // prima matrice
  matrixf mat2(KNMatrixRandom);     // seconda matrice
 
//--- calcola il prodotto delle matrici usando il metodo naive
  uint start=GetTickCount();
  matrixf matrix_naive=matrixf::Zeros(MN);// il risultato della moltiplicazione di due matrici è impostato qui
  for(int m=0m<Mm++)
    for(int k=0k<Kk++)
      for(int n=0n<Nn++)
        matrix_naive[m][n]+=mat1[m][k]*mat2[k][n];
  uint time_naive=GetTickCount()-start;   
     
//--- calcola il prodotto delle matrici tramite MatMull
  start=GetTickCount();
  matrixf matrix_matmul=mat1.MatMul(mat2);
  uint time_matmul=GetTickCount()-start;     
  
//--- calcola il prodotto delle matrici in OpenCL
  matrixf matrix_opencl=matrixf::Zeros(MN);
  int cl_ctx;             // contesto handle
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL not found, leaving");
    return;
   }
  int cl_prg;             // handle del programma 
  int cl_krn;             // handle del kernel
  int cl_mem_in1;         // primo (input) handle del buffer<
  int cl_mem_in2;         // secondo (input) handle del buffer<
  int cl_mem_out;         // terzo (input) handle del buffer<
//--- creo il programma e il kernel
  cl_prg = CLProgramCreate(cl_ctxclSrc);
  cl_krn = CLKernelCreate(cl_prg"matricesMul");
//--- creo tutti e tre i buffer per le tre matrici
  cl_mem_in1=CLBufferCreate(cl_ctxM*K*sizeof(float), CL_MEM_READ_WRITE);
  cl_mem_in2=CLBufferCreate(cl_ctxK*N*sizeof(float), CL_MEM_READ_WRITE);
//---terza matrice - output 
  cl_mem_out=CLBufferCreate(cl_ctxM*N*sizeof(float), CL_MEM_READ_WRITE);
//--- imposta gli argomenti del kernel
  CLSetKernelArgMem(cl_krn0cl_mem_in1);
  CLSetKernelArgMem(cl_krn1cl_mem_in2);
  CLSetKernelArgMem(cl_krn2cl_mem_out);
//--- scrive le matrici nei buffer del dispositivo
  CLBufferWrite(cl_mem_in10mat1);
  CLBufferWrite(cl_mem_in20mat2);
  CLBufferWrite(cl_mem_out0matrix_opencl);
//--- Ora d'Inizio di esecuzione del codice OpenCL
  start=GetTickCount();
//--- imposta i parametri dell'area di lavoro dell'attività ed esegue il programma OpenCL
  uint  offs[2] = {00};
  uint works[2] = {MN};
  start=GetTickCount();  
  bool ex=CLExecute(cl_krn2offsworks);
//--- calcola il risultato sulla matrice
  if(CLBufferRead(cl_mem_out0matrix_opencl))
    PrintFormat("[%d x %d] matrix read: "matrix_opencl.Rows(), matrix_opencl.Cols());
   else
      Print("CLBufferRead(cl_mem_out, 0, matrix_opencl failed. Error ",GetLastError()); 
  uint time_opencl=GetTickCount()-start;   
  Print("Compare calculation time using each method");
  PrintFormat("Naive product time = %d ms",time_naive);
  PrintFormat("MatMul product time = %d ms",time_matmul);
  PrintFormat("OpenCl product time = %d ms",time_opencl);  
//--- rilascia tutti i contesti OpenCL
  CLFreeAll(cl_ctxcl_prgcl_krncl_mem_in1cl_mem_in2cl_mem_out);
 
//--- confronta tra loro tutti i risultati delle matrici ottenuti
  Print("How many discrepancy errors are there between result matrices?");
  ulong errors=matrix_naive.Compare(matrix_matmul,(float)1e-12);
  Print("matrix_direct.Compare(matrix_matmul,1e-12)=",errors);
  errors=matrix_matmul.Compare(matrix_opencl,float(1e-12));
  Print("matrix_matmul.Compare(matrix_opencl,1e-12)=",errors);
/*
  Risultato:
   
   [3000 x 3000] lettura matrice: 
  Confronta il tempo di calcolo con ciascun metodo
   Naive tempo prodotto = 54750 ms
   MatMul tempo prodotto = 4578 ms
   OpenCl tempo prodotto = 922 ms
  Quanti errori di discrepanza ci sono tra i risultati delle matrici?
   matrix_direct.Confronto(matrix_matmul,1e-12)=0
   matrix_matmul.Confronto(matrix_opencl,1e-12)=0
*/  
 }
//+------------------------------------------------------------------+
//| Riempie la matrici con valori casuali                            |
//+------------------------------------------------------------------+
void MatrixRandom(matrixfm)
 {
  for(ulong r=0r<m.Rows(); r++)
   {
    for(ulong c=0c<m.Cols(); c++)
     {
      m[r][c]=(float)((MathRand()-16383.5)/32767.);
     }
   }
 }
//+------------------------------------------------------------------+
//| Rilascia tutti i contesti OpenCL                                 |
//+------------------------------------------------------------------+
void CLFreeAll(int cl_ctxint cl_prgint cl_krn,
               int cl_mem_in1int cl_mem_in2int cl_mem_out)
 {
//--- elimina tutti i contesti creati da OpenCL in ordine inverso
  CLBufferFree(cl_mem_in1);
  CLBufferFree(cl_mem_in2);
  CLBufferFree(cl_mem_out);
  CLKernelFree(cl_krn);
  CLProgramFree(cl_prg);
  CLContextFree(cl_ctx);
 }