OpenCL not found - страница 11

 
Aleksey Vyazmikin #:

Спасибо.

Это было увлекательно.

Положите файл итоговый в общую папку

или пропишите в файле Evolution-test.mq5 - в самой шапке привязку файла (будет передаваться тестеру) по имени(менять или добавлять при смене инструмента и тайм фрейма) и принудительное использование локальной папки терминала.

Учтите, если файла не будет и запустите тест, то придется перезапустить терминал, так как в кэше где то он запоминает, что файла нет - и ничего не поможет, кроме перезапуска...

Офигеть... всё заработало... 

Большущее Вам спасибо, Алексей!

 
Ivan Butko #:

Офигеть... всё заработало... 

Большущее Вам спасибо, Алексей!

Пожалуйста, успехов!

 
Aleksey Vyazmikin #:

Код полезный, в том плане, что его очень мало на OpenCL на этом ресурсе. Ну и тема специфичная - автор молодец так то.

//——————————————————————————————————————————————————————————————————————————————
//Функция для ядра
string GPU_kernel(int HL1NeuronCount,int HL2NeuronCount,int SampleCount,int SignalInCount)
{
  return(
        "//#pragma OPENCL EXTENSION cl_khr_fp64: enable                    \r\n"
        "#define HL1Count "     +(string)HL1NeuronCount+"                  \r\n"
        "#define HL2Count "     +(string)HL2NeuronCount+"                  \r\n"
        //----------------------------------------------------------------------
        "#define PorogSell1 "   +(string)PorogSell1+"                      \r\n"
        "#define PorogSell2 "   +(string)PorogSell2+"                      \r\n"
        "#define PorogBuy1  "   +(string)PorogBuy1+"                       \r\n"
        "#define PorogBuy2  "   +(string)PorogBuy2+"                       \r\n"
        //----------------------------------------------------------------------
        "#define SampleCount "  +(string)SampleCount+"                     \r\n"
        //----------------------------------------------------------------------
        "#define SignalInCount "+(string)SignalInCount+"                   \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)(SpreadTraining_P*Point())+"             \r\n"
        //----------------------------------------------------------------------
        "#define MinAllowTradeCount "+(string)(MinAllowTradeCount_P)+"     \r\n"
        "#define K_MinAllowTradeCount "+(string)(K_MinAllowTradeCount_P)+" \r\n"
        //----------------------------------------------------------------------

        //----------------------------------------------------------------------
        "__kernel void Work(__global ArrSa *Sample,                        \r\n"
        "                   __global ArrWe *Weights,                       \r\n"
        "                   __global ArrCr *Result,                        \r\n"
        "                   __global float *KoOfCrit)                      \r\n"
        "{                                                                 \r\n"
        //----------------------------------------------------------------------
        "  int thread       = get_global_id(0);                            \r\n"

        "  //------------------Переменные нейронной сети-------------------\r\n"
        "  float HL1[HL1Count];   // Нейроны первого скрытого слоя         \r\n"
        "  float HL2[HL2Count];   // Нейроны второго скрытого слоя         \r\n"
        "  ArrWe weights = 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"
        "  float PriceOpen = 0.0;  // цена открытия открытой сделки        \r\n"
        "  float Price     = 0.0;  // текущая цена                         \r\n"
        "  float High      = 0.0;  // максимум предыдущей свечи            \r\n"
        "  float Low       = 0.0;  // минимум предыдущей свечи             \r\n"
        "  bool  TypeBuy   = true; // тип сделки: buy-true, sell-false     \r\n"


        "  //--------------------Статистика торговли----------------------------\r\n"
        "  float PipsAllProfit    = 0.00001; // полученная прибыль в пипсах         + \r\n"
        "  float PipsAllLoss      =-0.00001; // полученный убыток в пипсах          - \r\n"
        "  int   TradeProfitCount = 1;       // кол-во приб. сделок                 + \r\n"
        "  int   TradeLossCount   = 1;       // кол-во уб. сделок                   + \r\n"
        "  float TradeDrawdown    = 0.0;     // просадка в трейде                   + \r\n"
        "  float SummDrawdown     = 0.00001; // сумма всех просадок для подсч.средн.+ \r\n"
        "  int   LossSeries       = 0;       // серия убыточных ордеров             + \r\n"
        "  int   MaxLossSer       = 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"
        "      HL1[u]=weights.C[cnt_W];                                    \r\n"
        "      cnt_W++;                                                    \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<SignalInCount;i++)                            \r\n"
        "      {                                                           \r\n"
        "        HL1[u]+=Sample[hist].C[i+3]*weights.C[cnt_W];             \r\n"
        "        cnt_W++;                                                  \r\n"
        "      }                                                           \r\n"
        "    }                                                             \r\n"
        "    //Посчитаем функцию активации для каждого скрытого нейрона    \r\n"
        "    for(int u=0;u<HL1Count;u++)                                   \r\n"
        "      HL1[u]=(2.0/(1.0+exp(-HL1[u]*7.0)))-1.0;                    \r\n"
        "    //---------------Обработаем второй скрытый слой---------------\r\n"
        "    //Добавим смещение точек насыщения нейрона: (+b)              \r\n"
        "    for(int u=0;u<HL2Count;u++)                                   \r\n"
        "    {                                                             \r\n"
        "      HL2[u]=weights.C[cnt_W];                                    \r\n"
        "      cnt_W++;                                                    \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"
        "        HL2[u]+=HL1[i]*weights.C[cnt_W];                          \r\n"
        "        cnt_W++;                                                  \r\n"
        "      }                                                           \r\n"
        "    }                                                             \r\n"
        "    //Посчитаем функцию активации для каждого скрытого нейрона    \r\n"
        "    for(int u=0;u<HL2Count;u++)                                   \r\n"
        "      HL2[u]=(2.0/(1.0+exp(-HL2[u]*7.0)))-1.0;                    \r\n"
        "    //-----------------Обработаем выходной слой-------------------\r\n"
        "    //Добавим смещение точек насыщения нейрона: (+b)              \r\n"
        "    Out=weights.C[cnt_W];                                         \r\n"
        "    cnt_W++;                                                      \r\n"
        "    //Сумма произведений нейронов предыдущего слоя и их весов:    \r\n"
        "    // (+w1*x1+...+wn*xn) для каждого нейрона                     \r\n"
        "    for(int i=0;i<HL2Count;i++)                                   \r\n"
        "    {                                                             \r\n"
        "      Out+=HL2[i]*weights.C[cnt_W];                               \r\n"
        "      cnt_W++;                                                    \r\n"
        "    }                                                             \r\n"
        //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

вот пример тестера для OCL, это прогон по истории нейронки. модуль алгоритма оптимизиции, конечно же, внешний.

гдето выкладывал уже, кому то может быть полезным как база для понимания как это дело работает. в коде OCL нет синхронизации ниток, на CPU работает быстрее чем на GPU задействуя все ядра, хотя может быть у меня видяха слабая была в 2012 году. время пришло переделать всё под текущие реалии. тогда я помню история по символу тупо не влезала в GPU, а тот обьём что влезал всёравно работал быстрее на CPU.

полностью код не позволяет разместить движёк форума, приложу в прикрепе.

Файлы:
OCL.txt  24 kb
 
Andrey Dik #:

вот пример тестера для OCL, это прогон по истории нейронки. модуль алгоритма оптимизиции, конечно же, внешний.

гдето выкладывал уже, кому то может быть полезным как база для понимания как это дело работает. в коде OCL нет синхронизации ниток, на CPU работает быстрее чем на GPU задействуя все ядра, хотя может быть у меня видяха слабая была в 2012 году. время пришло переделать всё под текущие реалии. тогда я помню история по символу тупо не влезала в GPU, а тот обьём что влезал всёравно работал быстрее на CPU.

полностью код не позволяет разместить движёк форума, приложу в прикрепе.

Спасибо за пример кода.

Однако, я не понял, как тут вообще реализовано последовательное обучение... По коду, кажется, что обучение проходит целиком по массивам истории, а где распараллеливание?

И, что это за типы переменных?

			    __global ArrSa *Sample,                        \r\n"
        "                   __global ArrWe *Weights,                       \r\n"
        "                   __global ArrCr *Result, 
 
Aleksey Vyazmikin #:

Спасибо за пример кода.

Однако, я не понял, как тут вообще реализовано последовательное обучение... По коду, кажется, что обучение проходит целиком по массивам истории, а где распараллеливание?

И, что это за типы переменных?

Этот код - соответствует одному прогону по истории (история подаётся как параметр), если сравнить со штатным оптимизатором, то один прогон на агенте.

Типы переменных - массивы структур.

Распараллеливание: представленный код OCL для одной нитки, таких ниток запускается заданное в параметрах движка OCL количество. Обычно - целиком популяция.

Что бы узнать, на какой конкретно нитке исполняется код служит переменная

int thread = get_global_id(0);
где get_global_id (0) - системная функция OCL.
 

Прогон по истории - самая дорогая операция, её и имеет смысл распараллеливать. Есть другая сторона медали - передача больших объёмов данных - узкое горлышко в операциях с устройствами OCL, на GPU выгоднее делать много расчетов, а не обмениваться большими объёмами данных с ОЗУ процессора. Поэтому такой код как я представил оптимальнее работает на CPU, да, ниток (логических ядер) у CPU меньше чем у GPU, но зато обмен большими данными с ОЗУ быстрее.

Было бы хорошо уметь один раз переслать историю в GPU перед началом расчетов и впредь только подкидывать в него набор переменных которые нужно оптимизировать. С этим я пока не разобрался, может кто то подскажет, а пока до сих пор отправляю историю на OCL целиком каждый раз.

 
Andrey Dik #:

Распараллеливание: представленный код OCL для одной нитки, таких ниток запускается заданное в параметрах движка OCL количество. Обычно - целиком популяция.

Так это генетика? Типа сразу посчитали разные варианты и выбрали лучший?

Andrey Dik #:

Типы переменных - массивы структур.

Т.е. это название структур по сути? Не знал, что так можно передавать в OpenCL. Думал, что минимум должно быть какое то описание там.

Andrey Dik #:

Было бы хорошо уметь один раз переслать историю в GPU перед началом расчетов и впредь только подкидывать в него набор переменных которые нужно оптимизировать. С этим я пока не разобрался, может кто то подскажет, а пока до сих пор отправляю историю на OCL целиком каждый раз.

Не совсем понятно, что не понятно :) Вы копируете массив с историей в буфер в начале скрипта или при инициализации советника, и дальше с ней работаете.

//---Кернелы OpenCL
   int index_kernel=0;
   int index_kernel_array_fill=1;
   int index_kernel_array_fill_d=2;
//---Инициализация файла с кернелами
   Print("Initialize=",m_OpenCL.Initialize(cl_tester,true));
//--- установка количества кернелов
   Print("SetKernelsCount=",m_OpenCL.SetKernelsCount(3));
//--- создание кернелов
   Print("0 KernelCreate=",m_OpenCL.KernelCreate(index_kernel,"CalcPred_All"));
   Print("1 KernelCreate=",m_OpenCL.KernelCreate(index_kernel_array_fill,"array_fill"));
   Print("2 KernelCreate=",m_OpenCL.KernelCreate(index_kernel_array_fill_d,"array_fill_d"));
//--- создание буферов - указать количество буферов
   Print("SetBuffersCount=",m_OpenCL.SetBuffersCount(9));
//--- копирование буфера на видеокарту
   Print("0 BufferFromArray=",m_OpenCL.BufferFromArray(0,arr_Data,0,Stolb_Total_Data*Strok_Total_Data,CL_MEM_READ_ONLY));
   Print("2 BufferFromArray=",m_OpenCL.BufferFromArray(2,arr_Target,0,Strok_Total_Data,CL_MEM_READ_ONLY));
   Print("3 BufferFromArray=",m_OpenCL.BufferFromArray(3,arr_Data_Q,0,Stolb_Total_Data*Strok_Total_Data,CL_MEM_READ_WRITE));

Потом уже в каком то цикле ниже по коду меняете параметры переменных массивов, трете временные буферы.

 
Aleksey Vyazmikin #:

1. Так это генетика? Типа сразу посчитали разные варианты и выбрали лучший?

2. Т.е. это название структур по сути? Не знал, что так можно передавать в OpenCL. Думал, что минимум должно быть какое то описание там.

3. Не совсем понятно, что не понятно :) Вы копируете массив с историей в буфер в начале скрипта или при инициализации советника, и дальше с ней работаете.

4. Потом уже в каком то цикле ниже по коду меняете параметры переменных массивов, трете временные буферы.

1. Вовсе не обязательно генетика. Просто сформированная пачка заданий. Популяционные в этом плане удобнее. Но сгодится и любой другой, который не требует обязательно последовательного получения результатов для оптимизации, по крайней мере который позволяет сформировать пачку заданий.

2. Да, просто названия структур. Удивительно, но как то это сильное колдунство работает, но нужно обязательно указывать размер структуры (или массива структур), иначе колдунство не сработает.

3.4. Вот с этим пока не понимаю. Надеюсь скоро руки дойдут и можно будет прямо в этой ветке позаниматься практически полезными извращениями с OCL. Да прибудет с нами сила.

 
Aleksey Vyazmikin #:

Типа сразу посчитали разные варианты и выбрали лучший?

не, не сразу. популяцию посчитали за эпоху.

к примеру, делаем размер популяции 512 (количество логических ядер/ниток), проводим 1000 эпох, получаем на выходе 512'000 прогонов. для сравнения - штатный оптимизатор МТ5 делает в среднем только 10'000 прогонов.

 
Билд 3520, FFT еще не работает.
Причина обращения: