5

I have created an Indicator using MQL5.

After Profiling, the program I read that 99% of my CPU is used by my OnCalculate().

Here is my function:

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 );
  }

Here is the result of profiling: profiling result

Kindly, let me know, how I can make the OnCalculate() work on GPU instead of CPU.

user3666197
  • 1
  • 6
  • 50
  • 92
Jaffer Wilson
  • 7,029
  • 10
  • 62
  • 139

1 Answers1

3

Which compute device, i.e. whether or not your program uses the CPU can be controlled via the CLContextCreate call:

int CLContextCreate(int device)

Where device could be e.g. CL_USE_GPU_ONLY, or a specific device number.

How to find out the number is described here.


However: What I can see from the profile is, that most of the time is spent Creating and Freeing OpenCL contexts. If the profile represents some kind of call stack, I'd assume that an OpenCL context is created and freed for every computation instead of doing it once during program initialisation and deinitialisation.

This seems to cost you 85 % of your runtime. So make sure, that you create OpenCL Context, Program, Kernel and Buffer objects during initialisation. For repeating computations, you only need do set kernel arguments, read/write buffer objects, and enqueue the kernel for execution

Hope that helps.

noma
  • 1,171
  • 6
  • 15
  • How I can initialize the buffer at `OnInit()` when the size of buffer is always changing? Kindly, help me modify the code to work with GPU completely if possible with lesser intervention of the CPU. – Jaffer Wilson Apr 30 '18 at 04:22
  • Start with one thing after the other, begin with the Context, as this seems to cost you the most according to your profile, then the other things. If you know an upper bound for the buffer size for your application, use that and only transfer the amount of data actually used, and set the amount of work-items accordingly (NDRange, global size). If it's too large (search for `CL_DEVICE_MAX_MEM_ALLOC_SIZE`), chunk your input. – noma May 01 '18 at 11:41
  • `CLGetDeviceInfo(cl_ctx,CL_DEVICE_VENDOR,h,s); Print("size = ",s); string str=CharArrayToString(h); Print(str);` I tried this command. Got the output as `OpenCL: GPU device 'GeForce GT 730' selected OpenCL device name: GeForce GT 730 size = 19 NVIDIA Corporation ` – Jaffer Wilson May 02 '18 at 04:19
  • Yes, that means you are already using the GPU and not the CPU, as it might be the first or only device on for which an OpenCL driver is installed on your system. As I wrote earlier, you can enforce a specific device type during context creation. If you're still unhappy with the performance, try what I proposed, and also measure the runtime of your kernel, e.g. the `CLEnqueueNDRangeKernel()` call, see [this](https://stackoverflow.com/a/29972269/7678171) for more details. – noma May 02 '18 at 11:54