OpenCL: test di implementazione interna in MQL5

 

Stiamo lavorando sul supporto OpenCL nativo direttamente in MQL5. In un paio di builds sarà disponibile pubblicamente.

Ecco un piccolo esempio di calcolo del frattale di Mandelbrot in OpenCL che accelera drasticamente i calcoli rispetto all'implementazione software. Il calcolo in OpenCL è 100 volte più veloce.


//+------------------------------------------------------------------+
//|                                                     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:

Stiamo lavorando sul supporto OpenCL nativo direttamente in MQL5. In un paio di builds sarà disponibile pubblicamente.

Ecco un piccolo esempio di calcolo del frattale di Mandelbrot in OpenCL che accelera drasticamente i calcoli rispetto all'implementazione software. Il calcolo in OpenCL è 100 volte più veloce.

Per poter eseguire lo script da soli, la libreria con le funzioni deve essere inclusa: CLContextCreate, CLProgramCreate, CLKernelCreate, CLBufferCreate, ecc. Cos'è questa libreria e dove posso trovarla?

 
tol64:

Per eseguire lo script, è necessario includere una libreria con funzioni: CLContextCreate, CLProgramCreate, CLKernelCreate, CLBufferCreate, ecc. Cos'è questa libreria e dove posso trovarla?

Nella cartella OpenCL ... In un paio di build ... :)
 
tol64:

Per eseguire lo script, è necessario includere una libreria con funzioni: CLContextCreate, CLProgramCreate, CLKernelCreate, CLBufferCreate, ecc. Cos'è questa libreria e dove posso trovarla?

Non avete bisogno di librerie; il supporto OpenCL in MQL5 è ora nativo.

Non ci sono file DLL aggiuntivi nel terminale. Al momento del caricamento, il terminale rileva la presenza di interfacce OpenCL sul sistema (sono aggiunte dal driver della scheda video). Tutti i produttori di schede video (NVIDIA, AMD, Intel) che forniscono OpenCL sono supportati.

È importante che i driver della scheda video siano aggiornati con il supporto delle interfacce OpenCL abilitato. Spesso, i driver regolari che vengono forniti con il computer o non hanno il supporto OpenCL o sono così vecchi che contengono errori critici nell'implementazione delle librerie OpenCL/CUDA. Di solito si può rimediare installando gli ultimi driver dal sito web del produttore.

 
Renat:
Renat, dovresti scrivere un articolo ora - come usare, caratteristiche, dove prendere il legno, ecc.
 
Renat:

Stiamo lavorando sul supporto OpenCL nativo direttamente in MQL5. Sarà disponibile pubblicamente in un paio di build.

Questo significa che gli agenti "video" possono essere collegati al meta tester? Opencl sarà, se possibile, usato in tutti/quasi tutti gli EA o solo in quelli che saranno scritti ("ground up") per usare le schede video?
 
Renat:

Questa è una grande notizia! Grazie.

TheXpert:
Renat, dovresti scrivere un articolo ora - come usare, caratteristiche, dove trovare l'hardware, ecc.

Sì, è necessario un articolo.

 
TheXpert:
Renat, dovresti scrivere un articolo su come usarlo, cosa c'è di speciale, dove trovare i driver e così via.

Ci sono già molti materiali su OpenCL sul web.

Potete iniziare da qui:

Tutte le funzioni OpenCL sono usate allo stesso modo in MQL5, quindi non sarà un problema trasferire le descrizioni da altri articoli al terreno MQL5.

 
joo:

Sì, l'articolo è necessario.

Sì, cercheremo di coprire l'uso di OpenCL sia nella documentazione che negli articoli.
 
WChas:
Questo significa che gli agenti "video" possono essere collegati al metatester? Opencl, se possibile, sarà usato in tutti/quasi tutti gli EA, o solo in quelli che saranno scritti ("ground up") per usare le schede video?

Sì, sarà possibile collegarsi - questa è l'intenzione.

Se i dispositivi OpenCL non saranno sull'agente, l'implementazione software funzionerà automaticamente.

 
Sono disposto a fornire la mia Radeon 6930 se è più redditizio delle criptovalute. 2-3 c.u. al giorno mi andrebbero bene. Se sarà inattivo come i processori Core i5 i7, imho non interessato