CLBufferWrite

Bir diziden OpenCL tamponuna veri yazar ve yazılan elemanların sayısına dönüş yapar.

uint  CLBufferWrite(
   int          buffer,                    // OpenCL tamponunun tanıtıcı değeri
   const void&  data[],                    // değerler için dizi
   uint         buffer_offset=0,           // OpenCL tamponunda bayt bazında konum değeri, varsayılan olarak 0
   uint         data_offset=0,             // Eleman sayısı bazında konum değeri, varsayılan olarak 0
   uint         data_count=WHOLE_ARRAY     // Dizideki yazılacak verilerin sayısı, varsayılan olarak bütün dizi
   );

Matrisleri ve vektörleri işlemek için versiyonlar da mevcuttur.

Matristen değerleri arabelleğe yazar ve başarılı olursa true değerini geri döndürür.

uint  CLBufferWrite(
   int           buffer,                    // OpenCL arabelleğine olan tanıtıcı
   uint          buffer_offset,             // OpenCL arabelleğinde bayt cinsinden ofset
   matrix<T>     &mat                       // arabelleğe yazılacak değerleri içeren matris
   );

Vektörden değerleri arabelleğe yazar ve başarılı olursa true değerini geri döndürür.

uint  CLBufferWrite(
   int           buffer,                    // OpenCL arabelleğine olan tanıtıcı
   uint          buffer_offset,             // OpenCL arabelleğinde bayt cinsinden ofset
   vector<T>     &vec                      // arabelleğe yazılacak değerleri içeren vektör
   );

Parametreler

buffer

[in]  Bir OpenCL tamponunun tanıtıcı değeri.

data[]

[in]  OpenCL tamponuna yazılacak verilerden oluşan dizi. Referans ile geçirilir.

buffer_offset

[in]  OpenCL tamponu içinde bayt bazında yazma başlangıç konumu. Yazma işlemi, varsayılan olarak tamponun en başından başlar.

data_offset

[in]  OpenCL tamponuna değerleri yazmak için, ilk dizi elemanının indisi. Varsayılan olarak dizinin en başındaki değerler alınır.

data_count

[in]  Yazılması gereken değerlerin sayısı. Varsayılan olarak, tüm dizi elemanları.

&mat

[out]  Verileri arabelleğe yazılacak matris şu üç türden herhangi biri olabilir: matrix, matrixf veya matrixc.

&vec

[out]  Verileri arabelleğe yazılacak vektör şu üç türden herhangi biri olabilir: vector, vectorf veya vectorc.

Dönüş değeri

Yazılan elemanların sayısı. Hata durumunda 0 dönüşü yapılır. Hata hakkında bilgi almak için GetLastError() fonksiyonunu kullanın.

Matris veya vektör başarıyla işlenirse true, aksi takdirde false geri döndürür.

Not

Tek boyutlu diziler için, OpenCL tamponuna yazılacak elemanların sayısı, AS_SERIES bayrağı hesaba katılarak hesaplanır.

İki veya daha fazla boyuta sahip diziler, tek boyutlu farz edilir. Bu durumda, data_offset parametresi, ilk boyuttaki elemanların sayısı değil, sunulan dizide atlanması gereken elemanların sayısıdır.

OpenCL'de MatMul metodu ve paralel hesaplama kullanılarak matris çarpımına örnek:

#define M       3000      // birinci matristeki satır sayısı
#define K       2000      // birinci matristeki sütun sayısı ikinci matristeki satır sayısına eşittir
#define N       3000      // ikinci matristeki sütun sayısı
 
//+------------------------------------------------------------------+
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";
//+------------------------------------------------------------------+
//| Komut dosyası başlatma fonksiyonu                                |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- rastgele sayı üreticisini başlat
  MathSrand((int)TimeCurrent());
//--- matrisleri rastgele değerlerle doldur
  matrixf mat1(MKMatrixRandom) ;    // birinci matris
  matrixf mat2(KNMatrixRandom);     // ikinci matris
 
//--- saf yöntem kullanarak matrislerin çarpımını hesapla
  uint start=GetTickCount();
  matrixf matrix_naive=matrixf::Zeros(MN);// iki matrisin çarpılmasının sonucu burada belirlenir
  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;   
     
//--- MatMul aracılığıyla matrislerin çarpımını hesapla
  start=GetTickCount();
  matrixf matrix_matmul=mat1.MatMul(mat2);
  uint time_matmul=GetTickCount()-start;     
  
//--- OpenCL'de matrislerin çarpımını hesapla
  matrixf matrix_opencl=matrixf::Zeros(MN);
  int cl_ctx;             // içerik tanıtıcısı
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL bulunamadı, çıkış yapılıyor");
    return;
   }
  int cl_prg;             // program tanıtıcısı
  int cl_krn;             // çekirdek tanıtıcısı
  int cl_mem_in1;         // birinci (girdi) arabellek tanıtıcısı
  int cl_mem_in2;         // ikinci (girdi) arabellek tanıtıcısı
  int cl_mem_out;         // üçüncü (çıktı) arabellek tanıtıcısı
//--- programı ve çekirdeği oluştur
  cl_prg = CLProgramCreate(cl_ctxclSrc);
  cl_krn = CLKernelCreate(cl_prg"matricesMul");
//--- üç matris için üç arabelleğin tümünü oluştur
  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);
//--- üçüncü matris - çıktı
  cl_mem_out=CLBufferCreate(cl_ctxM*N*sizeof(float), CL_MEM_READ_WRITE);
//--- çekirdek argümanlarını ayarla
  CLSetKernelArgMem(cl_krn0cl_mem_in1);
  CLSetKernelArgMem(cl_krn1cl_mem_in2);
  CLSetKernelArgMem(cl_krn2cl_mem_out);
//--- matrisleri cihaz arabelleklerine yaz
  CLBufferWrite(cl_mem_in10mat1);
  CLBufferWrite(cl_mem_in20mat2);
  CLBufferWrite(cl_mem_out0matrix_opencl);
//--- OpenCL kodunu çalıştırma zamanı başlangıcı
  start=GetTickCount();
//--- görev çalışma alanının parametrelerini ayarla ve OpenCL programını çalıştır
  uint  offs[2] = {00};
  uint works[2] = {MN};
  start=GetTickCount();  
  bool ex=CLExecute(cl_krn2offsworks);
//--- sonucu hesapla
  if(CLBufferRead(cl_mem_out0matrix_opencl))
    PrintFormat("[%d x %d] matris okuması: "matrix_opencl.Rows(), matrix_opencl.Cols());
   else
      Print("CLBufferRead(cl_mem_out, 0, matrix_opencl başarısız oldu. Hata ",GetLastError()); 
  uint time_opencl=GetTickCount()-start;   
  Print("Her yöntemi kullanarak hesaplama sürelerini karşılaştır");
  PrintFormat("Saf yöntemle çarpma süresi = %d ms",time_naive);
  PrintFormat("MatMul metoduyla çarpma süresi = %d ms",time_matmul);
  PrintFormat("OpenCl ile çarpma süresi = %d ms",time_opencl);  
//--- tüm OpenCL içeriklerini bırak
  CLFreeAll(cl_ctxcl_prgcl_krncl_mem_in1cl_mem_in2cl_mem_out);
 
//--- tüm sonuç matrisleri birbirleriyle karşılaştır
  Print("Sonuç matrisler arasında kaç tane tutarsızlık hatası var?");
  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);
/*
  Sonuç:
   
   [3000 x 3000] matris okuması: 
  Her yöntemi kullanarak hesaplama sürelerini karşılaştır
   Saf yöntemle çarpma süresi = 54750 ms
   MatMul metoduyla çarpma süresi = 4578 ms
   OpenCl ile çarpma süresi = 922 ms
  Sonuç matrisler arasında kaç tane tutarsızlık hatası var?
   matrix_direct.Compare(matrix_matmul,1e-12)=0
   matrix_matmul.Compare(matrix_opencl,1e-12)=0
*/  
 }
//+------------------------------------------------------------------+
//| Matrisi rastgele değerlerle doldur                               |
//+------------------------------------------------------------------+
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.);
     }
   }
 }
//+------------------------------------------------------------------+
//| Tüm OpenCL içeriklerini bırak                                    |
//+------------------------------------------------------------------+
void CLFreeAll(int cl_ctxint cl_prgint cl_krn,
               int cl_mem_in1int cl_mem_in2int cl_mem_out)
 {
//--- OpenCL tarafından ters sırada oluşturulan tüm içerikleri sil
  CLBufferFree(cl_mem_in1);
  CLBufferFree(cl_mem_in2);
  CLBufferFree(cl_mem_out);
  CLKernelFree(cl_krn);
  CLProgramFree(cl_prg);
  CLContextFree(cl_ctx);
 }