CLBufferWrite

Schreibt ein Array in einen OpenCL-Puffer und gibt die Anzahl der geschriebenen Elemente zurück.

uint  CLBufferWrite(
   int          buffer,                    // Handle auf den OpenCL-Puffer
   const void&  data[],                    // Array von Werten
   uint         buffer_offset=0,           // Offset im OpenCL-Puffer in Bytes, standardmäßig 0
   uint         data_offset=0,             // Offset im Array in Elemente, standardmäßig 0
   uint         data_count=WHOLE_ARRAY     // Anzahl der Werte im Array zu schreiben, standardmäßig das gesamte Array
   );

Es gibt auch Versionen für die Verarbeitung von Matrizen und Vektoren.

Die Werte aus der Matrix werden in den Puffer geschrieben und bei Erfolg wird true zurückgegeben.

uint  CLBufferWrite(
   int           buffer,                    // ein Handle zum Puffer von OpenCL
   uint          buffer_offset,             // ein Offset im OpenCL-Puffer in Bytes
   matrix<T>     &mat                       // die Matrix mit den Werten, die dem Puffer zugewiesen werden sollen
   );

Die Werte des Vektors werden in den Puffer geschrieben und bei Erfolg wird true zurückgegeben.

uint  CLBufferWrite(
   int           buffer,                    // ein Handle zum Puffer von OpenCL
   uint          buffer_offset,             // ein Offset im OpenCL-Puffer in Bytes
   vector<T>     &vec                       // der Vektor mit den Werten, die dem Puffer zugewiesen werden sollen
   );

Parameter

buffer

[in]  Handle auf den OpenCL-Puffer.

data[]

[in]  Das Array von Werten, die Sie in den OpenCL-Puffer schreiben möchten. Wird als Referenz übergeben.

buffer_offset

[in]  Offset im OpenCL-Puffer, mit dem Schreibung beginnt, in Bytes. Standardmäßig wird vom Anfang des Puffers geschrieben.

data_offset

[in]  Der Index des ersten Elements des Arrays aus dem die Werte für Schreiben in den OpenCL-Puffer beginnen. Standardmäßig werden die Werte vom Anfang des Arrays genommen.

data_count

[in]  Die Anzahl der Werte zu schreiben. Standardmäßig werden alle Werte des Arrays genommen.

mat

[out]  Die Matrix zum Lesen von Daten aus dem Puffer kann einer der drei Typen sein: matrix, matrixf oder matrixc.

vec

[out]  Der Vektor zum Lesen von Daten aus dem Puffer kann von einem der drei Typen sein: vector, vectorf oder vectorc.

Rückgabewert

Anzahl der geschriebenen Elemente. Im Falle eines Fehlers wird 0 zurückgegeben. Um Informationen über den Fehler zu erhalten, rufen Sie die Funktion GetLastError().

true, wenn eine Matrix oder ein Vektor erfolgreich verarbeitet wurde, ansonsten false.

Hinweis

Für eindimensionale Arrays, wird die Nummer des Elements, mit dem Lesung von Daten für Schreibung in den OpenCL-Puffer beginnt, unter Berücksichtigung der Flagge AS_SERIES ausgerechnet.

Ein Array von zwei oder mehr Dimensionen wird als eindimensional dargestellt. In diesem Fall ist data_Offset die Anzahl der Elemente, die in der Darstellung angegeben werden soll, nicht die Anzahl der Elemente in der ersten Dimension.

Beispiel für eine Matrixmultiplikation mit der Methode MatMul und paralleles Rechnen in OpenCL

#define M       3000      // die Anzahl der Zeilen der ersten Matrix
#define K       2000      // die Anzahl der Spalten in der ersten Matrix ist gleich der Anzahl der Zeilen in der zweiten 
#define N       3000      // die Anzahl der Spalten in der zweiten Matrix
 
//+------------------------------------------------------------------+
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";
//+------------------------------------------------------------------+
//| Skript Programm Start Funktion                                   |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- Initialisierung des Zufallszahlengenerators
  MathSrand((int)TimeCurrent());
//--- Füllen der Matrizen einer bestimmten Größe mit Zufallswerten
  matrixf mat1(MKMatrixRandom) ;    // erste Matrix
  matrixf mat2(KNMatrixRandom);     // zweite Matrix
 
//--- Berechnung des Produkts von Matrizen mit der naiven Methode
  uint start=GetTickCount();
  matrixf matrix_naive=matrixf::Zeros(MN);// das Ergebnis der Multiplikation zweier Matrizen wird hier ermittelt
  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;   
     
//--- Berechnung des Produkts von Matrizen über MatMull
  start=GetTickCount();
  matrixf matrix_matmul=mat1.MatMul(mat2);
  uint time_matmul=GetTickCount()-start;     
  
//--- Berechnung des Produkts von Matrizen in OpenCL
  matrixf matrix_opencl=matrixf::Zeros(MN);
  int cl_ctx;             // Kontext-Handle
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL nicht gefunden, Funktion wird verlassen");
    return;
   }
  int cl_prg;             // Programm-Handle 
  int cl_krn;             // Kernel-Handle
  int cl_mem_in1;         // Handle des ersten (Eingabe) Puffers
  int cl_mem_in2;         // Handle des zweiten (Eingabe) Puffers
  int cl_mem_out;         // Handle des dritten (Eingabe) Puffers
//--- das Programm und den Kernel erstellen
  cl_prg = CLProgramCreate(cl_ctxclSrc);
  cl_krn = CLKernelCreate(cl_prg"matricesMul");
//--- alle drei Puffer für drei Matrizen erstellen
  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);
//--- dritte Matrix - Ausgabe
  cl_mem_out=CLBufferCreate(cl_ctxM*N*sizeof(float), CL_MEM_READ_WRITE);
//--- Setzen der Kernel-Argumente
  CLSetKernelArgMem(cl_krn0cl_mem_in1);
  CLSetKernelArgMem(cl_krn1cl_mem_in2);
  CLSetKernelArgMem(cl_krn2cl_mem_out);
//--- Matrizen in die Gerätepuffer schreiben
  CLBufferWrite(cl_mem_in10mat1);
  CLBufferWrite(cl_mem_in20mat2);
  CLBufferWrite(cl_mem_out0matrix_opencl);
//--- Startzeit der Ausführung des OpenCL-Codes
  start=GetTickCount();
//--- die Parameter des Arbeitsbereichs der Aufgabe festlegen und das OpenCL-Programm ausführen
  uint  offs[2] = {00};
  uint works[2] = {MN};
  start=GetTickCount();  
  bool ex=CLExecute(cl_krn2offsworks);
//--- Berechnen des Ergebnisses in der Matrix
  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);  
//--- alle OpenCL-Kontexte freigeben
  CLFreeAll(cl_ctxcl_prgcl_krncl_mem_in1cl_mem_in2cl_mem_out);
 
//--- alle erhaltenen Ergebnismatrizen miteinander vergleichen
  Print("Wie viele Diskrepanzfehler gibt es zwischen den Ergebnismatrizen?");
  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);
/*
  Ergebnis:
   
   [3000 x 3000] matrix read: 
  Vergleich der Berechnungszeit von jeder Methode
   Naive product time = 54750 ms
   MatMul product time = 4578 ms
   OpenCl product time = 922 ms
  Wie viele Diskrepanzfehler gibt es zwischen den Ergebnismatrizen?
   matrix_direct.Compare(matrix_matmul,1e-12)=0
   matrix_matmul.Compare(matrix_opencl,1e-12)=0
*/  
 }
//+------------------------------------------------------------------+
//| Füllen der Matrix mit Zufallszahlen                              |
//+------------------------------------------------------------------+
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.);
     }
   }
 }
//+------------------------------------------------------------------+
//| Freigeben aller OpenCL Kontexte                                  |
//+------------------------------------------------------------------+
void CLFreeAll(int cl_ctxint cl_prgint cl_krn,
               int cl_mem_in1int cl_mem_in2int cl_mem_out)
 {
//--- alle von OpenCL erstellten Kontexte in umgekehrter Reihenfolge löschen
  CLBufferFree(cl_mem_in1);
  CLBufferFree(cl_mem_in2);
  CLBufferFree(cl_mem_out);
  CLKernelFree(cl_krn);
  CLProgramFree(cl_prg);
  CLContextFree(cl_ctx);
 }