Как заставить функцию OnCalculate() пользовательского индикатора использовать GPU в MQL5/OpenCL?

Я создал индикатор с помощью MQL5.

После профилирования программы я прочитал, что 99% моего процессора используется моим OnCalculate().

Вот моя функция:

int OnCalculate( const int     rates_total,
                 const int     prev_calculated,
                 const int     begin,
                 const double &price[]
                 )
  {
//--- check for bars count
      float tempprice[];
      ArrayResize( tempprice, ArraySize( price ) );
      if (  rates_total <  InpMAPeriod - 1 + begin ) return( 0 ); // not enough bars for calculation
//--- first calculation or number of bars was changed
      if (  prev_calculated == 0 ) ArrayInitialize( ExtLineBuffer, 0 );

      ArrayCopy( tempprice, price );
//--- sets first bar from what index will be draw
      PlotIndexSetInteger( 0, PLOT_DRAW_BEGIN, InpMAPeriod - 1 + begin );

      switch( InpMAMethod )
      {
         case MODE_EMA:  Execute_Me( price,
                                    "CalculateEMA",
                                     rates_total,
                                     prev_calculated,
                                     begin
                                     );
                         break;
         case MODE_LWMA: Execute_Me( price,
                                    "CalculateLWMA",
                                     rates_total,
                                     prev_calculated,
                                     begin
                                     );
                         break;
         case MODE_SMMA: Execute_Me( price,
                                    "CalculateSmoothedMA",
                                     rates_total,
                                     prev_calculated,
                                     begin
                                     );
                         break;
         case MODE_SMA:  Execute_Me( price,
                                    "CalculateSimpleMA",
                                     rates_total,
                                     prev_calculated,
                                     begin
                                     );
                         break;
     }
     return( rates_total );
  }

Вот результат профилирования: результат профилирования

Пожалуйста, дайте мне знать, как я могу заставить OnCalculate() работать на GPU, а не на CPU.


person Jaffer Wilson    schedule 24.04.2018    source источник


Ответы (1)


Каким вычислительным устройством, т. е. использует ли ваша программа ЦП, можно управлять с помощью CLContextCreate< /а> вызов:

int CLContextCreate(int device)

Где device может быть, например. CL_USE_GPU_ONLY или номер конкретного устройства.

Как узнать номер описано здесь.


Однако: Из профиля я вижу, что большая часть времени тратится на создание и освобождение контекстов OpenCL. Если профиль представляет собой какой-то стек вызовов, я бы предположил, что контекст OpenCL создается и освобождается для каждого вычисления, а не один раз во время инициализации и деинициализации программы.

Кажется, это стоит вам 85% вашего времени выполнения. Поэтому убедитесь, что вы создали объекты OpenCL Context, Program, Kernel и Buffer во время инициализации. Для повторяющихся вычислений вам нужно только установить аргументы ядра, прочитать/записать объекты буфера и поставить ядро ​​в очередь для выполнения.

Надеюсь, это поможет.

person noma    schedule 27.04.2018
comment
Как я могу инициализировать буфер в OnInit(), когда размер буфера постоянно меняется? Пожалуйста, помогите мне изменить код для полной работы с графическим процессором, если это возможно, с меньшим вмешательством процессора. - person Jaffer Wilson; 30.04.2018
comment
Начните с одного за другим, начните с Контекста, так как это будет стоить вам больше всего в соответствии с вашим профилем, а затем с другими вещами. Если вы знаете верхнюю границу размера буфера для вашего приложения, используйте ее и передайте только объем фактически используемых данных и соответственно установите количество рабочих элементов (NDRange, глобальный размер). Если он слишком большой (ищите CL_DEVICE_MAX_MEM_ALLOC_SIZE), разделите ввод. - person noma; 01.05.2018
comment
CLGetDeviceInfo(cl_ctx,CL_DEVICE_VENDOR,h,s); Print("size = ",s); string str=CharArrayToString(h); Print(str); Я попробовал эту команду. Получил вывод как OpenCL: GPU device 'GeForce GT 730' selected OpenCL device name: GeForce GT 730 size = 19 NVIDIA Corporation - person Jaffer Wilson; 02.05.2018
comment
Да, это означает, что вы уже используете GPU, а не CPU, поскольку это может быть первое или единственное устройство, для которого в вашей системе установлен драйвер OpenCL. Как я уже писал ранее, вы можете принудительно указать определенный тип устройства во время создания контекста. Если вы все еще недовольны производительностью, попробуйте то, что я предложил, а также измерьте время работы вашего ядра, например. вызов CLEnqueueNDRangeKernel(), см. эту дополнительную информацию. - person noma; 02.05.2018