OpenCL: MQL5'te dahili uygulama testleri

 

OpenCL için doğrudan MQL5'te yerel destek üzerinde çalışıyoruz. Birkaç yapı içinde halka açık olacak.

Burada, yazılım uygulamasına kıyasla hesaplamaları büyük ölçüde hızlandıran, OpenCL'de Mandelbrot fraktalını hesaplamaya yönelik küçük bir çalışma örneği verilmiştir. OpenCL'deki hesaplamanın 100 kat daha hızlı olduğu ortaya çıktı.


 //+------------------------------------------------------------------+
//|                                                     ocl_test.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link       "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Код функции OpenCL                                               |
//+------------------------------------------------------------------+
const string cl_src=
       "__kernel void MFractal(                                    \r\n"
       "                       float x0,                           \r\n"
       "                       float y0,                           \r\n"
       "                       float x1,                           \r\n"
       "                       float y1,                           \r\n"
       "                       uint  max,                          \r\n"
       "              __global uint *out)                          \r\n"
       "  {                                                        \r\n"
       "   size_t  w = get_global_size(0);                         \r\n"
       "   size_t  h = get_global_size(1);                         \r\n"
       "   size_t gx = get_global_id(0);                           \r\n"
       "   size_t gy = get_global_id(1);                           \r\n"
       "   float dx = x0 + gx * (x1-x0) / (float) w;               \r\n"
       "   float dy = y0 + gy * (y1-y0) / (float)h;                \r\n"
       "   float x  = 0;                                           \r\n"
       "   float y  = 0;                                           \r\n"
       "   float xx = 0;                                           \r\n"
       "   float yy = 0;                                           \r\n"
       "   float xy = 0;                                           \r\n"
       "   uint i = 0;                                             \r\n"
       "   while ((xx+yy)<4 && i<max)                              \r\n"
       "     {                                                     \r\n"
       "      xx = x*x;                                            \r\n"
       "      yy = y*y;                                            \r\n"
       "      xy = x*y;                                            \r\n"
       "      y = xy+xy+dy;                                        \r\n"
       "      x = xx-yy+dx;                                        \r\n"
       "      i++;                                                 \r\n"
       "     }                                                     \r\n"
       "   if(i==max)                                              \r\n"
       "      out[w*gy+gx] = 0;                                    \r\n"
       "   else                                                    \r\n"
       "      out[w*gy+gx] = (uint)((float)0xFFFFFF/(float)max)*i; \r\n"
       "  }                                                        \r\n" ;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#define SIZE_X 512
#define SIZE_Y 512
//+------------------------------------------------------------------+
//| Заголовок BMP файла                                              |
//+------------------------------------------------------------------+
struct BitmapHeader
  {
   ushort             type;
   uint               size;
   uint               reserv;
   uint               offbits;
   uint               imgSSize;
   uint               imgWidth;
   uint               imgHeight;
   ushort             imgPlanes;
   ushort             imgBitCount;
   uint               imgCompression;
   uint               imgSizeImage;
   uint               imgXPelsPerMeter;
   uint               imgYPelsPerMeter;
   uint               imgClrUsed;
   uint               imgClrImportant;
  };
//+------------------------------------------------------------------+
//| Запись битмапа в файл                                            |
//+------------------------------------------------------------------+
bool SaveBitmapToFile( const string filename, uint &bitmap[], const BitmapHeader &info)
  {
//--- откроем файл
   int file= FileOpen (filename, FILE_WRITE | FILE_BIN );
   if (file== INVALID_HANDLE )
     {
       Print ( __FUNCTION__ , " error opening '" ,filename, "'" );
       return ( false );
     }
//--- запишем заголовок и само тело
   if ( FileWriteStruct (file,info)== sizeof (info))
     {
       if ( FileWriteArray (file,bitmap)== ArraySize (bitmap))
        {
         FileClose (file);
         return ( true );
        }
     }
//--- неудачно получилось, удалим файл от греха подальше
   FileClose (file);
   FileDelete (filename);
   Print ( __FUNCTION__ , " error writting '" ,filename, "'" );
//--- вернем ошибку
   return ( false );
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart ()
  {
//--- инициализируем OpenCL объекты
   int cl_ctx=CLContextCreate();
   int cl_prg=CLProgramCreate(cl_ctx,cl_src);
   int cl_krn=CLKernelCreate(cl_prg, "MFractal" );
   int cl_mem=CLBufferCreate(cl_ctx,SIZE_X*SIZE_Y* sizeof ( float ),CL_MEM_READ_WRITE);
//--- подготовимся к выполению
   float x0       =- 2 ;
   float y0       =- 0.5 ;
   float x1       =- 1 ;
   float y1       = 0.5 ;
   uint   max      = 20000 ;
   uint   offset[ 2 ]={ 0 , 0 };
   uint   work  [ 2 ]={SIZE_X,SIZE_Y};
//--- выставляем неизменяемые параметры функции OpenCL
   CLSetKernelArg(cl_krn, 4 ,max);
   CLSetKernelArgMem(cl_krn, 5 ,cl_mem);
//--- подготовим буфер для вывода пикселей
   uint buf[];  
   ArrayResize (buf,SIZE_X*SIZE_Y);
//--- подготовим заголовок
   BitmapHeader info;
   ZeroMemory (info);
   info.type          = 0x4d42 ;
   info.size          = sizeof (info)+SIZE_X*SIZE_Y* 4 ;
   info.offbits       = sizeof (info);
   info.imgSSize      = 40 ;
   info.imgWidth      =SIZE_X;
   info.imgHeight     =SIZE_Y;
   info.imgPlanes     = 1 ;
   info.imgBitCount   = 32 ;
   info.imgCompression= 0 ;                 // BI_RGB
   info.imgSizeImage  =SIZE_X*SIZE_Y* 4 ;   
//--- создаём объект для вывода графики
   ObjectCreate ( 0 , "x" , OBJ_BITMAP_LABEL , 0 , 0 , 0 );
   ObjectSetInteger ( 0 , "x" , OBJPROP_XDISTANCE , 0 );
   ObjectSetInteger ( 0 , "x" , OBJPROP_YDISTANCE , 50 );
//--- рендерим пока не остоновят снаружи
   while (! IsStopped ())
     {
       uint x= GetTickCount ();
       //--- выставляем плавающие параметры
      CLSetKernelArg(cl_krn, 0 ,x0);
      CLSetKernelArg(cl_krn, 1 ,y0);
      CLSetKernelArg(cl_krn, 2 ,x1);
      CLSetKernelArg(cl_krn, 3 ,y1);
       //--- рендерим кадр
      CLExecute(cl_krn, 2 ,offset,work);                  
       //--- забираем данные кадра
      CLBufferRead(cl_mem,buf);
       //--- выведем время рендера
       Comment ( GetTickCount ()-x);
       //--- сохраняем кадр в памяти и рисуем его
      SaveBitmapToFile( "Mandelbrot.bmp" ,buf,info);
       ObjectSetString ( 0 , "x" , OBJPROP_BMPFILE , NULL );
       ObjectSetString ( 0 , "x" , OBJPROP_BMPFILE , "\\Files\\Mandelbrot.bmp" );
       ChartRedraw ();
       //--- небольшая задержка и обновление параметров для следующего кадра
       Sleep ( 10 );
      x0+= 0.001 f;
      x1-= 0.001 f;
      y0+= 0.001 f;
      y1-= 0.001 f;
     }
//--- удаляем объекты OpenCL
   CLBufferFree(cl_mem);
   CLKernelFree(cl_krn);
   CLProgramFree(cl_prg);
   CLContextFree(cl_ctx);
  }
//+------------------------------------------------------------------+
OpenCL: Мост в параллельные миры
OpenCL: Мост в параллельные миры
  • 2012.05.16
  • Sceptic Philozoff
  • www.mql5.com
В конце января 2012 года компания-разработчик терминала MetaTrader 5 анонсировала нативную поддержку OpenCL в MQL5. В статье на конкретном примере изложены основы программирования на OpenCL в среде MQL5 и приведены несколько примеров "наивной" оптимизации программы по быстродействию.
 
Renat :

OpenCL için doğrudan MQL5'te yerel destek üzerinde çalışıyoruz. Birkaç yapı içinde halka açık olacak.

Burada, yazılım uygulamasına kıyasla hesaplamaları büyük ölçüde hızlandıran, OpenCL'de Mandelbrot fraktalını hesaplamaya yönelik küçük bir çalışma örneği verilmiştir. OpenCL'deki hesaplamanın 100 kat daha hızlı olduğu ortaya çıktı.

Ve betiği kendi başınıza çalıştırmak için kitaplığı şu işlevlerle bağlamanız gerekir: CLContextCreate , CLProgramCreate , CLKernelCreate , CLBufferCreate , vb. Bu kütüphane nedir ve nereden edinebilirim?

 
tol64 :

Ve betiği kendi başınıza çalıştırmak için kitaplığı şu işlevlerle bağlamanız gerekir: CLContextCreate , CLProgramCreate , CLKernelCreate , CLBufferCreate , vb. Bu kütüphane nedir ve nereden edinebilirim?

OpenCL klasöründe... birkaç derlemede .. :)
 
tol64 :

Ve betiği kendi başınıza çalıştırmak için kitaplığı şu işlevlerle bağlamanız gerekir: CLContextCreate , CLProgramCreate , CLKernelCreate , CLBufferCreate , vb. Bu kütüphane nedir ve nereden edinebilirim?

Kitaplık gerekmez, MQL5'teki OpenCL desteği artık yereldir.

Terminalde ek DLL dosyası yok. Yükleme sırasında terminal, sistemde OpenCL arabirimlerinin varlığını algılar (video kartı sürücüsü tarafından eklenirler). OpenCL sağlayan tüm grafik kartı üreticileri (NVIDIA, AMD, Intel) desteklenir.

OpenCL arabirimleri için etkinleştirilmiş destekle ekran kartı sürücülerinin güncel olması önemlidir. Genellikle standart sürücüler, OpenCL desteği olmayan veya OpenCL / CUDA kitaplıklarının uygulanmasında kritik hatalar içerecek kadar eski bir bilgisayarla birlikte gelir. Bütün bunlar genellikle üreticinin web sitesinden en son sürücüleri yükleyerek ele alınır.

 
Renat :
Renat, şimdi bir makale yazmalısın - nasıl kullanılır, özellikleri, yakacak odun nereden alınır, vb.
 
Renat :

OpenCL için doğrudan MQL5'te yerel destek üzerinde çalışıyoruz. Birkaç yapı içinde halka açık olacak.

Bu, "video" aracılarının meta test cihazına bağlanabileceği anlamına mı geliyor? Opencl mümkünse tüm/çoğu uzmanlarda mı yoksa sadece ekran kartlarının kullanımı için yazılacak ("keskin") olanlarda mı kullanılacak?
 
Renat :

Harika haber! Teşekkür ederim.

TheXpert :
Renat, şimdi bir makale yazmalısın - nasıl kullanılır, özellikleri, yakacak odun nereden alınır, vb.

Evet, gerekli olacak.

 
TheXpert :
Renat, şimdi bir makale yazmalısın - nasıl kullanılır, özellikleri, yakacak odun nereden alınır, vb.

Nette OpenCL ile ilgili bir çok materyal var.

Buradan başlayabilirsiniz:

Tüm OpenCL işlevleri MQL5'te bire bir kullanılır, bu nedenle diğer makalelerden MQL5'e açıklamaların aktarılmasında sorun olmayacaktır.

 
joo :

Evet, gerekli olacak.

Evet, hem dökümanlarda hem de makalelerde OpenCL kullanımını anlatmaya çalışacağız.
 
WChas :
Bu, "video" aracılarının meta test cihazına bağlanabileceği anlamına mı geliyor? Opencl, mümkünse tüm/çoğu uzmanlarda mı yoksa sadece ekran kartlarının kullanımı için yazılacak ("keskin") olanlarda mı kullanılacak?

Evet, bağlanmak mümkün olacak - odak noktası tam olarak bu.

Aracı üzerinde OpenCL cihazı yoksa, yazılım uygulaması otomatik olarak çalışacaktır.

 
Kripto para biriminden daha karlı çalışıyorsa Radeon 6930'umu sağlamaya hazırım. Günde 2-3 USD ile memnun olacağım. Ayrıca Core i5 i7 işlemciler gibi boşta kalacaksa, IMHO ilginç değil