Вот что можно сделать с OpenCL прямо в терминале MetaTrader 5 без всяких DLL - страница 4

 
Alexey Volchanskiy:
Да, я немного знаком с OCL, в курсе. Так и не нужно весь советник в карту грузить, пусть грузятся участки параллельного кода, их, как правило, проценты от всего кода. 
Так огромного ускорения получить для обычных советников не получится. Всё упрётся в пропускную способность агентов.
 
Vitalie Postolache:
Почему же я при оптимизации вижу только ядра ЦП (Core i5, 8 ядер - 8 агентов), при наличии NVIDIA 780GTX? 

А вы OpenCL используете в своем коде?

Скорее всего вы думаете, что любой ваш код должен на графическую карту грузиться. Что не есть правда.

Настоятельно рекомендую почитать наши статьи про OpenCL в MetaTrader 5, где все детально объяснено как работает:

 

Для того, что бы получить существенное ускорение нужно отправлять советник целиком в GPU, но для этого нужно писать собственный тестер. 

Вот пример такого тестера, нейронная сеть с торговой логикой, код 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"
          
 

продолжение кода:

          "    //Сумма произведений нейронов предыдущего слоя и их весов:                  \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:

Это демонстрация не только расчетов на GPU в MQL5 коде, но и графических возможностей терминала:

Полный исходный код в виде скрипта приложен. Ошибка на OpenCL 1.2 исправлена.

Это круто! Буду делать 3д графики, пригодится. Да и скорость неплохая получится для мегапроекта. Сегодня же приду, затестю)
 
Andrey Dik:

продолжение кода:

Кстати, а можно в OCL послать код не в виде строчной простыни, а как-то в виде файла? А то выглядит страшненько.

 
Alexey Volchanskiy:

Кстати, а можно в OCL послать код не в виде строчной простыни, а как-то в виде файла? А то выглядит страшненько.

Код OCL это просто строка string. Читаете файл в переменную string и отправляете её в GPU, таким образов будет не страшненько.
 
У меня не пашет(
 

Важно отметить, что сейчас в конце 2016 года уже можно закладываться на наличие OpenCL в целевых системах.

Даже если нет GPU, то OpenCL будет работать на CPU, используя все ядра. Вот как выглядит набор устройств:

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.60GHz with OpenCL 1.2 (24 units, 2598 MHz, 32680 Mb, version 2117.13 (sse2,avx), rating 85)

Терминал автоматически выбирает наиболее быстрое устройство по рейтингу производительности. Также можно выбрать вручную любое устройство через функцию CLContextCreate.

К сожалению, на Windows XP об OpenCL надо забыть. Да и вообще об 32 битных операционках - на носу 2017 год.

Более неприятна ситуация с Nvidia, которая по сути саботирует стандарт OpenCL и не внедряет OpenCL 2.0. Сначала саботировала внедрение OpenCL 1.2, теперь OpenCL 2.0. Это она делает ради продвижения своей собственной реализации CUDA, что вредит всему сообществу.

Кроме того, Nvidia специально понижает точность в своих геймерских картах, чтобы ограничить их использование в математике и простимулировать покупки специализированных карт (Tesla).

На этом фоне AMD выглядит выигрышной не только за счет явно более быстрых мат расчетов (майнерские фермы на АМД обычно собирают), но и за свою стратегию открытых стандартов(они очень много открыли и продвигают в паблик). Внедрение OpenCL 2.0 в AMD картах вплотную приблизил эту спецификацию к возможностям CUDA и теперь вообще нет смысла закладываться на CUDA.

 
Скоро мы разрешим OpenCL в MQL5 Cloud Network как минимум для CPU реализаций.
Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Заработать деньги, продавая мощности своего компьютера для сети распределенных вычислений MQL5 Cloud Network
Причина обращения: