#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(M, K, MatrixRandom) ;    // erste Matrix
   matrixf mat2(K, N, MatrixRandom);     // zweite Matrix
  
 //--- Berechnung des Produkts von Matrizen mit der naiven Methode
   uint start=GetTickCount();
   matrixf matrix_naive=matrixf::Zeros(M, N);// das Ergebnis der Multiplikation zweier Matrizen wird hier ermittelt
   for(int m=0; m<M; m++)
     for(int k=0; k<K; k++)
       for(int n=0; n<N; n++)
         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(M, N);
   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_ctx, clSrc);
   cl_krn = CLKernelCreate(cl_prg, "matricesMul");
 //--- alle drei Puffer für drei Matrizen erstellen
   cl_mem_in1=CLBufferCreate(cl_ctx, M*K*sizeof(float), CL_MEM_READ_WRITE);
   cl_mem_in2=CLBufferCreate(cl_ctx, K*N*sizeof(float), CL_MEM_READ_WRITE);
 //--- dritte Matrix - Ausgabe
   cl_mem_out=CLBufferCreate(cl_ctx, M*N*sizeof(float), CL_MEM_READ_WRITE);
 //--- Setzen der Kernel-Argumente
   CLSetKernelArgMem(cl_krn, 0, cl_mem_in1);
   CLSetKernelArgMem(cl_krn, 1, cl_mem_in2);
   CLSetKernelArgMem(cl_krn, 2, cl_mem_out);
 //--- Matrizen in die Gerätepuffer schreiben
   CLBufferWrite(cl_mem_in1, 0, mat1);
   CLBufferWrite(cl_mem_in2, 0, mat2);
   CLBufferWrite(cl_mem_out, 0, matrix_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] = {0, 0};
   uint works[2] = {M, N};
   start=GetTickCount();  
   bool ex=CLExecute(cl_krn, 2, offs, works);
 //--- Berechnen des Ergebnisses in der Matrix
   if(CLBufferRead(cl_mem_out, 0, matrix_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_ctx, cl_prg, cl_krn, cl_mem_in1, cl_mem_in2, cl_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(matrixf& m)
  {
   for(ulong r=0; r<m.Rows(); r++)
    {
     for(ulong c=0; c<m.Cols(); c++)
      {
       m[r][c]=(float)((MathRand()-16383.5)/32767.);
      }
    }
  }
 //+------------------------------------------------------------------+
 //| Freigeben aller OpenCL Kontexte                                  |
 //+------------------------------------------------------------------+
 void CLFreeAll(int cl_ctx, int cl_prg, int cl_krn,
                int cl_mem_in1, int cl_mem_in2, int 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);
  } 
 |