# OpenCL：MQL5での内部実装テスト

MQL5で直接OpenCLの ネイティブサポートに 取り組んでいます。数回のビルドで一般に公開される予定です。

ここでは、OpenCLによるマンデルブロフラクタル計算の小さな実用例を紹介します。この計算では、ソフトウェア実装に比べて計算が劇的に高速化されます。OpenCLでの計算が100倍速くなる。

```//+------------------------------------------------------------------+
//|                                                     ocl_test.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              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 файла                                              |
//+------------------------------------------------------------------+
{
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");
//--- подготовимся к выполению
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);
//--- подготовим заголовок
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);
//--- забираем данные кадра
//--- выведем время рендера
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: Мост в параллельные миры
• 2012.05.16
• Sceptic Philozoff
• www.mql5.com
В конце января 2012 года компания-разработчик терминала MetaTrader 5 анонсировала нативную поддержку OpenCL в MQL5. В статье на конкретном примере изложены основы программирования на OpenCL в среде MQL5 и приведены несколько примеров "наивной" оптимизации программы по быстродействию.

Renat:

MQL5で直接OpenCLのネイティブサポートに取り組んでいます。数回のビルドで一般に公開される予定です。

ここでは、OpenCLによるマンデルブロフラクタル計算の小さな実用例を紹介します。この計算では、ソフトウェア実装に比べて計算が劇的に高速化されます。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で使用されるのでしょうか、それとも、ビデオカードを使用するように書かれた（「グランドアップ」）ものだけに使用されるのでしょうか？

Renat:

それは素晴らしいニュースですね。ありがとうございます。

TheXpert です。
レナート 今すぐ記事を書いてください - 使い方、特徴、ハードの入手先など。

そうです、記事が必要なのです。

TheXpert:
レナートさん、使い方はもちろん、何が特別なのか、ドライバはどこで手に入るのか、などなど、とにかく記事を書いてください。

OpenCLについては、すでにWeb上で多くの資料が公開されています。

ここからスタートすることができます。

MQL5では全てのOpenCL関数が同等に使用されますので、他の記事からMQL5の土壌に記述を移すことは問題ありません。

joo:

そう、記事は必要なのです。

はい、ドキュメントと記事の両方でOpenCLの利用を カバーするようにします。

WChas:
ビデオ」エージェントがメーテーターに接続できるということでしょうか。Openclは、可能であれば、すべての/ほとんどのEAで使用されるのでしょうか、それとも、ビデオカードを使用するように書かれた（「グランドアップ」）ものだけで使用されるのでしょうか？

そうですね、プラグインが可能になる--そのつもりです。

OpenCLデバイスがエージェント上にない場合、ソフトウェア実装が自動的に動作します。