CLProgramCreate

Bir kaynak kodundan OpenCL programı oluşturur.

int  CLProgramCreate(
   int           context,     // Bir OpenCL bağlamının tanıtıcı değeri
   const string  source       // Kaynak kodu
   );

OpenCL programı oluşturan ve derleyici mesajlarını referans ile geçirilen dizgi değişkene yazan aşırı yüklenmiş fonksiyon.

int  CLProgramCreate(
   int           context,     // Bir OpenCL bağlamının tanıtıcı değeri
   const string  source,      // Kaynak kodu
   string       &build_log    // Derleme kayıtlarını alması için eklenen dizgi değişken
   );

Parametreler

context

[in]  OpenCL bağlamının tanıtıcı değeri.

source

[in]  OpenCL programını içeren kaynak kodu dizesi.

&build_log

[in]  OpenCL derleyicisinin mesajını almak için bir dizgi değişken.

Dönüş Değeri

Başarılı olması durumunda bir OpenCL nesnesinin tanıtıcı değeri. Hata durumunda -1 dönüşü yapar. Hata hakkında bilgi almak için GetLastError() fonksiyonunu kullanın.

Not

Hali hazırda kullanılmakta olan hata kodları şu şekildedir:

  • ERR_OPENCL_INVALID_HANDLE – OpenCL bağlamı için hatalı tanıtıcı değer.
  • ERR_INVALID_PARAMETER – hatalı string parametre.
  • ERR_NOT_ENOUGH_MEMORY – işlemi tamamlamak için yeterli hafıza yok.
  • ERR_OPENCL_PROGRAM_CREATE – OpenCL içsel hatası, veya derleme hatası.

Bazı ekran kartlarında varsayılan olarak double tipli sayılarla çalışılamaz. Bu durum 5105 numaralı hata değerine yol açabilir. double tipli sayılarla çalışabilmek için lütfen OpenCL programınıza şu direktifi ekleyin: #pragma OPENCL EXTENSION cl_khr_fp64 : enable.  Ama ekran kartı double tipli sayıları desteklemiyorsa bu direktifin de bir yararı olmayacaktır.

Örnek:

//+------------------------------------------------------------------+
//| OpenCL kernel                                                    |
//+------------------------------------------------------------------+
const string
cl_src=
       //--- varsayılan olarak GPU double tipli sayıları desteklemiyor
       //--- double tipi ile çalışabilmek için cl_khr_fp64 direktifi kullanılır
       "#pragma OPENCL EXTENSION cl_khr_fp64 : enable      \r\n"
       //--- OpenCL kernel fonksiyonu
       "__kernel void Test_GPU(__global double *data,      \r\n"
       "                       const    int N,             \r\n"
       "                       const    int total_arrays)  \r\n"
       "  {                                                \r\n"
       "   uint kernel_index=get_global_id(0);             \r\n"
       "   if (kernel_index>total_arrays) return;          \r\n"
       "   uint local_start_offset=kernel_index*N;         \r\n"
       "   for(int i=0; i<N; i++)                          \r\n"
       "     {                                             \r\n"
       "       data[i+local_start_offset] *= 2.0;          \r\n"
       "     }                                             \r\n"
       "  }                                                \r\n";
//+------------------------------------------------------------------+
//| Test_CPU                                                         |
//+------------------------------------------------------------------+
bool Test_CPU(double &data[],const int N,const int id,const int total_arrays)
  {
//--- dizi büyüklüğünü denetle
   if(ArraySize(data)==0) return(false);
//--- dizi indisini denetle
   if(id>total_arrays) return(false);
//--- id numaralı dizi için yerel başlangıç payını hesapla
   int local_start_offset=id*N;
//--- elemanları 2 ile çarp
   for(int i=0; i<N; i++)
     {
      data[i+local_start_offset]*=2.0;
     }
   return true;
  }
//---
#define ARRAY_SIZE   100  // dizi büyüklüğü
#define TOTAL_ARRAYS 5    // dizi sayısı
//--- OpenCL işleyicileri
int cl_ctx;  // OpenCL bağlam işleyicisi
int cl_prg;  // OpenCL program işleyicisi
int cl_krn;  // OpenCL kernel işleyicisi
int cl_mem;  // OpenCL tampon işleyicisi
//---
double DataArray1[]; // CPU hesaplamaları için veri dizisi
double DataArray2[]; // GPU hesplamaları için veri dizisi
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
//--- OpenCL nesnelerini başlat
//--- OpenCL bağlamı oluştur
   if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
     {
      Print("OpenCL bulunamadı. Hata=",GetLastError());
      return(1);
     }
//--- OpenCL programı oluştur
   if((cl_prg=CLProgramCreate(cl_ctx,cl_src))==INVALID_HANDLE)
     {
      CLContextFree(cl_ctx);
      Print("OpenCL programı oluşturulamadı. Hata=",GetLastError());
      return(1);
     }
//--- OpenCL kerneli oluştur
   if((cl_krn=CLKernelCreate(cl_prg,"Test_GPU"))==INVALID_HANDLE)
     {
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("OpenCL kerneli oluşturulamadı. Hata=",GetLastError());
      return(1);
     }
//--- OpenCL tamponu oluştur
   if((cl_mem=CLBufferCreate(cl_ctx,ARRAY_SIZE*TOTAL_ARRAYS*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
     {
      CLKernelFree(cl_krn);
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("OpenCL tamponu oluşturulamadı. Hata=",GetLastError());
      return(1);
     }
//--- OpenCL kerneli içinsabit parametreleri ayarla
   CLSetKernelArgMem(cl_krn,0,cl_mem);
   CLSetKernelArg(cl_krn,1,ARRAY_SIZE);
   CLSetKernelArg(cl_krn,2,TOTAL_ARRAYS);
//--- veri dizilerini hazırla
   ArrayResize(DataArray1,ARRAY_SIZE*TOTAL_ARRAYS);
   ArrayResize(DataArray2,ARRAY_SIZE*TOTAL_ARRAYS);
//--- verileri dizilere gir
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- j numaralı dizi için yerel başlangıç payını hesapla
      uint local_offset=j*ARRAY_SIZE;
      //--- j numaralı diziyi hazırla
      for(int i=0; i<ARRAY_SIZE; i++)
        {
         //--- dizileri MathCos(i+j) fonksiyonu ile doldur;
         DataArray1[i+local_offset]=MathCos(i+j);
         DataArray2[i+local_offset]=MathCos(i+j);
        }
     };
//--- CPU hesaplamasını denetle
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- j numaralı dizinin hesaplanması
      Test_CPU(DataArray1,ARRAY_SIZE,j,TOTAL_ARRAYS);
     }
//--- CLExecute parametrelerini ayarla
   uint  offset[]={0};
//--- global iş büyüklüğü
   uint  work[]={TOTAL_ARRAYS};
//--- veriyi OpenCL tamponuna yaz
   CLBufferWrite(cl_mem,DataArray2);
//--- OpenCL kernelini çalıştır
   CLExecute(cl_krn,1,offset,work);
//--- OpenCL tamponundan verileri oku
   CLBufferRead(cl_mem,DataArray2);
//--- toplam hata
   double total_error=0;
//--- sonuçları karşılaştır ve htayı hesapla
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- j numaralı dizi için yerel başlangıç payını hesapla
      uint local_offset=j*ARRAY_SIZE;
      //--- sonuçları karşılaştır
      for(int i=0; i<ARRAY_SIZE; i++)
        {
         double v1=DataArray1[i+local_offset];
         double v2=DataArray2[i+local_offset];
         double delta=MathAbs(v2-v1);
         total_error+=delta;
         //--- ilk ve son dizileri göster
         if((j==0) || (j==TOTAL_ARRAYS-1))
            PrintFormat("%d dizi arasından %d numarlı dizi, eleman [%d]:  %f, %f, [hata]=%f",TOTAL_ARRAYS,j+1,i,v1,v2,delta);
        }
     }
   PrintFormat("Toplam hata: %f",total_error);
//--- OpenCL nesnelerini sil
//--- OpenCL tamponunu boşlalt
   CLBufferFree(cl_mem);
//--- OpenCL kernelini serbest bırak
   CLKernelFree(cl_krn);
//--- OpenCL programını srbest bırak
   CLProgramFree(cl_prg);
//--- OpenCL bağlamıı serbest bırak
   CLContextFree(cl_ctx);
//---
   return(0);
  }