OpenCL:MQL5中的内部实现测试

 

我们正在努力在MQL5中直接提供 本地OpenCL支持。在几个构建中,它将被公开提供。

下面是一个在OpenCL中计算Mandelbrot分形的小工作实例,与软件实现相比,它极大地加快了计算速度。OpenCL中的计算速度是100倍。


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

我们正在努力在MQL5中直接提供本地OpenCL支持。在几个构建中,它将被公开提供。

下面是一个在OpenCL中计算Mandelbrot分形的小工作实例,与软件实现相比,它极大地加快了计算速度。OpenCL中的计算速度是100倍。

为了能够自己运行该脚本,必须包括带有函数的库。CLContextCreateCLProgramCreateCLKernelCreateCLBufferCreate 等。这个图书馆是什么,我在哪里可以得到它?

 
tol64:

为了运行该脚本,你需要包含一个带有函数的库。CLContextCreateCLProgramCreateCLKernelCreateCLBufferCreate 等。这个图书馆是什么,我在哪里可以得到它?

在OpenCL文件夹中...在几项建设中...:)
 
tol64:

为了运行该脚本,你需要包含一个带有函数的库。CLContextCreateCLProgramCreateCLKernelCreateCLBufferCreate 等。这个图书馆是什么,我在哪里可以得到它?

你不需要任何库;MQL5中的OpenCL支持现在是原生的。

终端中没有额外的DLL文件。在加载时,终端会检测系统上是否有OpenCL接口(它们是由显卡驱动添加的)。所有提供OpenCL的显卡制造商(NVIDIA、AMD、Intel)都支持。

重要的是,显卡驱动程序必须是最新的,并启用OpenCL接口支持。通常情况下,与计算机捆绑的驱动程序要么不支持OpenCL,要么太老了,以至于在实现OpenCL/CUDA库时包含关键错误。这通常可以通过从制造商的网站安装最新的驱动程序来补救。

 
Renat:
雷纳特,你现在应该写一篇文章--如何使用,特点,哪里有木头,等等。
 
Renat:

我们正在努力在MQL5中直接提供本地OpenCL支持。它将在几个构建中公开提供。

这是否意味着 "视频 "代理可以连接到元测试器?如果可能的话,Opencl将被用于所有/大部分的EA,还是只用于那些将被编写("从头开始")以使用显卡的EA?
 
Renat:

这是个好消息!谢谢你。

TheXpert
雷纳特,你现在应该写一篇文章--如何使用,功能,在哪里获得硬件,等等。

是的,需要一篇文章。

 
TheXpert:
雷纳特,你应该写一篇关于如何使用它的文章,它有什么特别之处,在哪里可以得到驱动程序等等。

网络上已经有很多关于OpenCL 的材料。

你可以从这里开始。

所有的OpenCL函数在MQL5中都是平等使用的,所以将其他文章中的描述转移到MQL5土壤中不会有问题。

 
joo:

是的,这篇文章是必要的。

是的,我们将尝试在文档和文章中涵盖OpenCL的使用
 
WChas:
这是否意味着 "视频 "代理可以连接到计量器上?如果可能的话,Opencl将被用于所有/大部分的EA,还是只用于那些将被编写("从头开始")以使用显卡的EA?

是的,它将有可能插入--这就是意图。

如果OpenCL设备不会出现在代理上,软件实现将自动工作。

 
如果比加密货币更有利可图,我愿意提供我的Radeon 6930。每天2-3c.u.适合我使用。如果它将像酷睿i5 i7处理器那样闲置,我认为不感兴趣。