Voici ce que vous pouvez faire avec OpenCL directement dans MetaTrader 5, sans aucune DLL. - page 4

 
Alexey Volchanskiy:
Oui, je connais un peu l'OCL, j'en suis conscient. Il n'est pas nécessaire de charger l'ensemble de l'EA dans la carte, laissez-les charger quelques fragments de code parallèles, ils représentent généralement un pourcentage du code entier.
De cette façon, vous n'obtiendrez pas un énorme gain de vitesse pour les Expert Advisors standard. Tout sera limité par la bande passante des agents.
 
Vitalie Postolache:
Alors, pourquoi est-ce que je ne vois que les cœurs du CPU (Core i5, 8 cœurs - 8 agents) lors de l'optimisation alors que j'ai une NVIDIA 780GTX ?

Utilisez-vous OpenCL dans votre code ?

Vous pensez probablement que tout votre code doit être chargé sur la carte graphique. Ce qui n'est pas vrai.

Je vous recommande vivement de lire notre article sur OpenCL dans MetaTrader 5 où tout est expliqué en détail comment cela fonctionne :

 

Afin d'obtenir une accélération significative, vous devez envoyer l'ensemble du conseiller au GPU, mais pour cela, vous devez écrire votre propre testeur.

Voici un exemple d'un tel testeur, un réseau de neurones avec logique de trading, code OCL :

//————————————————————————————————————————————————————————————————————————————————————————————————
//Функция для ядра
string GPU_kernel( int hl1NeuronCount,
                   int hl2NeuronCount,
                   int sampleCount,
                   int signalCount)
{
   return
         (
           "#define HL1Count "              + ( string )hl1NeuronCount + "                     \r\n"
           "#define HL2Count "              + ( string )hl2NeuronCount + "                     \r\n"
           //------------------------------------------------------------------------------------
           "#define NeuronSensitivity  "    + ( string )NeuronSensitivity_P + "                \r\n"
           //------------------------------------------------------------------------------------
           "#define sampleCount "           + ( string )sampleCount + "                        \r\n"
           //------------------------------------------------------------------------------------
           "#define signalCount "           + ( string )signalCount + "                        \r\n"
           //------------------------------------------------------------------------------------
           "#define StrArrSaSize "          + ( string )( sizeof (ArrSample) / sizeof ( float )) + "\r\n"
           "typedef struct{float C[StrArrSaSize];} ArrSa;                                   \r\n"
           //------------------------------------------------------------------------------------
           "#define StrArrWeSize "          + ( string )( sizeof (ArrWe) / sizeof ( float )) + "    \r\n"
           "typedef struct{float C[StrArrWeSize];} ArrWe;                                   \r\n"
           //------------------------------------------------------------------------------------
           "#define StrArrCrSize "          + ( string )( sizeof (ArrCr) / sizeof ( float )) + "    \r\n"
           "typedef struct{float C[StrArrCrSize];}ArrCr;                                    \r\n"
           //------------------------------------------------------------------------------------
           "#define Spread "                + ( string )(Spread_P * Point ()) + "               \r\n"
           //------------------------------------------------------------------------------------
           "#define Point "                 + ( string ) Point () + "                            \r\n"
           "#define SL "                    + ( string )(StopLoss_P * Point ()) + "             \r\n"
           "#define TP "                    + ( string )(TakeProfit_P * Point ()) + "           \r\n"
           //------------------------------------------------------------------------------------
           "                                                                                \r\n"
           "__kernel void Work(__global ArrSa *Sample,                                      \r\n"
           "                   __global ArrWe *Weights,                                     \r\n"
           "                   __global ArrCr *Result)                                      \r\n"
           "{                                                                               \r\n"
           "  int thread       = get_global_id(0);                                          \r\n"
           "                                                                                \r\n"
           "  //------------------Переменные нейронной сети---------------------------------\r\n"
           "  float nHL1 [HL1Count];   // Нейроны первого скрытого слоя                     \r\n"
           "  float nHL2 [HL2Count];   // Нейроны второго скрытого слоя                     \r\n"
           "  ArrWe parametr = Weights[thread];  // Параметры системы                       \r\n"
           "  int   cnt_W    = 0;     // счетчик весов                                      \r\n"
           "  float out      = 0.0;   // выход сети                                         \r\n"
           "                                                                                \r\n"
           "  //-------------------Переменные для торговли----------------------------------\r\n"
           "  float temp             = 0.0;    // для временного хранения чего нибудь       \r\n"
           "                                                                                \r\n"
           "  //---параметры цены                                                           \r\n"
           "  float priceASK            = 0.0;   // текущая Ask цена                        \r\n"
           "  float priceBID            = 0.0;   // текущая Bid цена                        \r\n"
           "  float pricePrevHighASK    = 0.0;   // максимум предыдущей свечи Ask           \r\n"
           "  float pricePrevHighBID    = 0.0;   // максимум предыдущей свечи Bid           \r\n"
           "  float pricePrevLowASK     = 0.0;   // минимум предыдущей свечи Ask            \r\n"
           "  float pricePrevLowBID     = 0.0;   // минимум предыдущей свечи Bid            \r\n"
           "                                                                                \r\n"
           "  float posType             = 0.0;   // тип сделки:                             \r\n"
           "                                     // 1.0 - buy,                              \r\n"
           "                                     //-1.0 - sell;                             \r\n"
           "                                     // 0.0 - нет открытой сделки               \r\n"
           "  float posPriceClose       = 0.0;                                              \r\n"
           "  float posPriceClosePrevHi = 0.0;                                              \r\n"
           "  float posPriceClosePrevLo = 0.0;                                              \r\n"
           "                                                                                \r\n"
           "  //-----------------Текущие показатели позиции---------------------------------\r\n"
           "  float posPriceSL          = 0.0;    // цена StopLoss открытой сделки          \r\n"
           "  float posPriceTP          = 0.0;    // цена TakeProfit открытой сделки        \r\n"
           "                                                                                \r\n"
           "  //--------------------Статистика торговли-------------------------------------\r\n"
           "  int   StTradeProfitCount  = 0;      // кол-во приб. сделок                    \r\n"
           "  int   StTradeLossCount    = 0;      // кол-во уб. сделок                      \r\n"
           "                                                                                \r\n"
           "  int   StTradeLossSeries   = 0;     // текущая серия убыточных ордеров         \r\n"
           "  int   StTradeMaxLossSer   = 0;     // самая длинная серия уб.ордеров          \r\n"
           "                                                                                \r\n"
           "  //-----------------------Тут прогон по истории--------------------------------\r\n"
           "  for(int hist = 0;hist < sampleCount;hist++)                                   \r\n"
           "  {                                                                             \r\n"
           "    cnt_W = 0;                                                                  \r\n"
           "    //---------------Обработаем первый скрытый слой-----------------------------\r\n"
           "    //Добавим смещение точек насыщения нейрона: (+b)                            \r\n"
           "    for(int u = 0;u < HL1Count;u++)                                             \r\n"
           "    {                                                                           \r\n"
           "      nHL1[u] = parametr.C[cnt_W];                                              \r\n"
           "      cnt_W++;                                                                  \r\n"
           "    }                                                                           \r\n"
           "                                                                                \r\n"
           "    //Сумма произведений нейронов предыдущего слоя и их весов:                  \r\n"
           "    // (+w1*x1+...+wn*xn) для каждого нейрона                                   \r\n"
           "    for(int u = 0;u < HL1Count;u++)                                             \r\n"
           "    {                                                                           \r\n"
           "      for(int i = 0;i < signalCount;i++)                                        \r\n"
           "      {                                                                         \r\n"
           "        nHL1[u] += Sample[hist].C[i + 3] * parametr.C[cnt_W];                   \r\n"
           "        cnt_W++;                                                                \r\n"
           "      }                                                                         \r\n"
           "    }                                                                           \r\n"
           "                                                                                \r\n"
           "    //Посчитаем функцию активации для каждого скрытого нейрона                  \r\n"
           "    for(int u = 0;u < HL1Count;u++)                                             \r\n"
           "    {                                                                           \r\n"
           "      nHL1[u] = 5.0 * nHL1[u] / (1.0 + fabs(4.02 * nHL1[u]));                   \r\n"
           "    }                                                                           \r\n"
           "                                                                                \r\n"
           "    //---------------Обработаем второй скрытый слой-----------------------------\r\n"
           "    //Добавим смещение точек насыщения нейрона: (+b)                            \r\n"
           "    for(int u = 0;u < HL2Count;u++)                                             \r\n"
           "    {                                                                           \r\n"
           "      nHL2[u] = parametr.C[cnt_W];                                              \r\n"
           "      cnt_W++;                                                                  \r\n"
           "    }                                                                           \r\n"
           "                                                                                \r\n"
          
 

suite de code :

          "    //Сумма произведений нейронов предыдущего слоя и их весов:                  \r\n"
           "    // (+w1*x1+...+wn*xn) для каждого нейрона                                   \r\n"
           "    for(int u = 0;u < HL2Count;u++)                                             \r\n"
           "    {                                                                           \r\n"
           "      for(int i = 0;i < HL1Count;i++)                                           \r\n"
           "      {                                                                         \r\n"
           "        nHL2[u] += nHL1[i] * parametr.C[cnt_W];                                 \r\n"
           "        cnt_W++;                                                                \r\n"
           "      }                                                                         \r\n"
           "    }                                                                           \r\n"
           "                                                                                \r\n"
           "    //Посчитаем функцию активации для каждого скрытого нейрона                  \r\n"
           "    for(int u = 0;u < HL2Count;u++)                                             \r\n"
           "    {                                                                           \r\n"
           "      nHL2[u] = 5.0 * nHL2[u] / (1.0 + fabs(4.02 * nHL2[u]));                   \r\n"
           "    }                                                                           \r\n"
           "                                                                                \r\n"
           "    //-----------------Обработаем выходной слой---------------------------------\r\n"
           "    //Добавим смещение точек насыщения нейрона: (+b)                            \r\n"
           "    out = parametr.C[cnt_W];                                                    \r\n"
           "    cnt_W++;                                                                    \r\n"
           "                                                                                \r\n"
           "    //Сумма произведений нейронов предыдущего слоя и их весов:                  \r\n"
           "    // (+w1*x1+...+wn*xn) для каждого нейрона                                   \r\n"
           "    for(int i = 0;i < HL2Count;i++)                                             \r\n"
           "    {                                                                           \r\n"
           "      out += nHL2[i] * parametr.C[cnt_W];                                       \r\n"
           "      cnt_W++;                                                                  \r\n"
           "    }                                                                           \r\n"
           "    //==========================================================================\r\n"
           "                                                                                \r\n"
           "                                                                                \r\n"
           "    //==========================================================================\r\n"
           "    priceASK         = Sample[hist].C[0] + Spread;                              \r\n"
           "    priceBID         = Sample[hist].C[0];                                       \r\n"
           "                                                                                \r\n"
           "    pricePrevHighASK = Sample[hist].C[1] + Spread;                              \r\n"
           "    pricePrevHighBID = Sample[hist].C[1];                                       \r\n"
           "                                                                                \r\n"
           "    pricePrevLowASK  = Sample[hist].C[2] + Spread;                              \r\n"
           "    pricePrevLowBID  = Sample[hist].C[2];                                       \r\n"
           "                                                                                \r\n"
           "    //-----------------проверка условий на выход из рынка-----------------------\r\n"
           "    // если есть открытая поза                                                  \r\n"
           "    if(posType != 0.0)                                                          \r\n"
           "    {                                                                           \r\n"
           "      if(posType == 1.0)                                                        \r\n"
           "      {                                                                         \r\n"
           "        posPriceClose       = priceBID;                                         \r\n"
           "        posPriceClosePrevHi = pricePrevHighBID;                                 \r\n"
           "        posPriceClosePrevLo = pricePrevLowBID;                                  \r\n"
           "      }                                                                         \r\n"
           "      else                                                                      \r\n"
           "      {                                                                         \r\n"
           "        posPriceClose       = priceASK;                                         \r\n"
           "        posPriceClosePrevHi = pricePrevHighASK;                                 \r\n"
           "        posPriceClosePrevLo = pricePrevLowASK;                                  \r\n"
           "      }                                                                         \r\n"
           "                                                                                \r\n"
           "                                                                                \r\n"
           "      // может уже сработал SL?                                                 \r\n"
           "      if(posType * (posPriceSL - posPriceClose) >= 0.0 ||                       \r\n"
           "         posType * (posPriceSL - posPriceClosePrevLo) >= 0.0)                   \r\n"
           "      {                                                                         \r\n"
           "        // на одну убыточную сделку больше                                      \r\n"
           "        StTradeLossCount++;                                                     \r\n"
           "        // текущая серия убыточных сделок увеличилась                           \r\n"
           "        StTradeLossSeries++;                                                    \r\n"
           "        // если серия уб. сделок больше чем в истори, то запомним               \r\n"
           "        StTradeMaxLossSer = (StTradeMaxLossSer < StTradeLossSeries) ?           \r\n"
           "                            StTradeLossSeries : StTradeMaxLossSer;              \r\n"
           "        // позиция закрыта                                                      \r\n"
           "        posType = 0.0;                                                          \r\n"
           "      }                                                                         \r\n"
           "      // нет, SL не сработал                                                    \r\n"
           "      else                                                                      \r\n"
           "      {                                                                         \r\n"
           "        // может уже сработал TP?                                               \r\n"
           "        if(posType * (posPriceClose - posPriceTP) >= 0.0 ||                     \r\n"
           "           posType * (posPriceClosePrevHi - posPriceTP) >= 0.0)                 \r\n"
           "        {                                                                       \r\n"
           "          // на одну прибыльную сделку больше                                   \r\n"
           "          StTradeProfitCount++;                                                 \r\n"
           "          // текущая серия убыточных сделок закончилась                         \r\n"
           "          StTradeLossSeries = 0;                                                \r\n"
           "          // позиция закрыта                                                    \r\n"
           "          posType = 0.0;                                                        \r\n"
           "        }                                                                       \r\n"
           "      }                                                                         \r\n"
           "                                                                                \r\n"
           "    }                                                                           \r\n"
           "    //--------------------------------------------------------------------------\r\n"
           "                                                                                \r\n"
           "                                                                                \r\n"
           "    //-----------------проверка сигнала на вход в рынок-------------------------\r\n"
           "    // если нет открытых поз проверим возможность открытия                      \r\n"
           "    if(posType == 0.0 && hist < (sampleCount - 1))                              \r\n"
           "    {                                                                           \r\n"
           "      // если есть сигнал на покупку                                            \r\n"
           "      if(NeuronSensitivity < out)                                               \r\n"
           "      {                                                                         \r\n"
           "        posPriceTP   = priceASK + TP;                                           \r\n"
           "        posPriceSL   = priceASK - SL;                                           \r\n"
           "        posType = 1.0;                                                          \r\n"
           "      }                                                                         \r\n"
           "      // если есть сигнал на продажу                                            \r\n"
           "      if(out < -NeuronSensitivity)                                              \r\n"
           "      {                                                                         \r\n"
           "        posPriceSL   = priceBID + SL;                                           \r\n"
           "        posPriceTP   = priceBID - TP;                                           \r\n"
           "        posType = -1.0;                                                         \r\n"
           "      }                                                                         \r\n"
           "    }                                                                           \r\n"
           "  }                                                                             \r\n"
           "                                                                                \r\n"
           "                                                                                \r\n"
           "  //----------------------------------------------------------------------------\r\n"
           "  float Profit = ((float)StTradeProfitCount*TP)-((float)StTradeLossCount*SL);   \r\n"
           "  Result[thread].C[0] =  Profit;                                                \r\n"
           "  Result[thread].C[1] = -StTradeMaxLossSer;                                     \r\n"
           "}                                                                               \r\n"
          );
}
//————————————————————————————————————————————————————————————————————————————————————————————————
 
Renat Fatkhullin:

Il s'agit d'une démonstration non seulement des calculs GPU dans le code MQL5, mais aussi des capacités graphiques du terminal :

Le code source complet sous forme de script est joint. Le bogue sur OpenCL 1.2 a été corrigé.

C'est cool ! Je vais faire des graphiques en 3d, ça va être pratique. Et la vitesse sera bonne pour un méga projet. Je viendrai aujourd'hui et je ferai un essai.)
 
Andrey Dik:

la suite du code :

À propos, est-il possible d'envoyer du code à l'OCL d'une manière ou d'une autre sous la forme d'un fichier, plutôt que sous la forme d'un poste de travail ? Sinon, ça donne un peu la chair de poule.

 
Alexey Volchanskiy:

À propos, est-il possible d'envoyer du code à OCL non pas sous forme de feuille ligne par ligne, mais en quelque sorte sous forme de fichier ? Ça a l'air un peu effrayant.

Le code OCL est juste une chaîne de caractères. Vous pouvez lire le fichier dans la variable string et l'envoyer au GPU.
 
Cela ne fonctionne pas pour moi.
 

Il est important de noter qu'aujourd'hui, fin 2016, il est déjà possible de revendiquer la présence d'OpenCL dans les systèmes cibles.

Même s'il n'y a pas de GPU, OpenCL fonctionnera sur le CPU en utilisant tous les cœurs. Voici à quoi ressemble l'ensemble des dispositifs :

OpenCL  Device #0: GPU Advanced Micro Devices, Inc. Hawaii with OpenCL 2.0 (44 units, 1080 MHz, 8192 Mb, version 2117.13 (VM), rating 1760)
OpenCL  Device #1: CPU GenuineIntel Intel(R) Xeon(R) CPU E5-2690 v3 @ 2.60 GHz with OpenCL 1.2 (24 units, 2598 MHz, 32680 Mb, version 2117.13 (sse2,avx), rating 85)

Le terminal sélectionne automatiquement le dispositif le plus rapide en fonction de la cote de performance. Il est également possible de sélectionner manuellement n'importe quel dispositif via la fonction CLContextCreate.

Malheureusement, oubliez OpenCL sur Windows XP. Et les systèmes d'exploitation 32 bits en général - nous sommes en 2017.

Plus désagréable encore est la situation de Nvidia, qui sabote essentiellement la norme OpenCL et ne met pas en œuvre OpenCL 2.0. Elle a d'abord saboté la mise en œuvre d'OpenCL 1.2, puis d'OpenCL 2.0. Il fait cela pour promouvoir sa propre mise en œuvre de CUDA, ce qui nuit à l'ensemble de la communauté.

Par ailleurs, Nvidia abaisse délibérément la précision de ses cartes pour gamers afin de limiter leur utilisation en mathématiques et de stimuler l'achat de cartes spécialisées (Tesla).

Dans ce contexte, AMD semble l'emporter, non seulement en raison de sa rapidité mathématique (les fermes d'exploitation minière sont généralement construites sur AMD), mais aussi en raison de sa stratégie de normes ouvertes (elle s'est beaucoup ouverte et fait entrer dans le domaine public). L'introduction d'OpenCL 2.0 dans les cartes AMD a rapproché cette spécification des capacités de CUDA et il est désormais inutile de préparer le terrain pour CUDA.

 
Bientôt, nous autoriserons OpenCL dans MQL5 Cloud Network, au moins pour les implémentations CPU.
Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Заработать деньги, продавая мощности своего компьютера для сети распределенных вычислений MQL5 Cloud Network