1
votes

Here is the function that I am trying to work with:

#define SIZE_X 512
#define SIZE_Y 512

int   cl_ctx;
int   cl_prg;
int   cl_krn;
int   cl_mem;

float ExponentialMA( const int     position,
                     const int     period,
                     const double  prev_value,
                     const double &price[]
                     )
{
//---
   float result[]; 
   ArrayResize(result,1);
   float pr=2.0/(period+1.0);
   Print( "Reality:  :) ", (float)price[position]*pr+prev_value*(1-pr) );

   if (  period > 0 )     //--- calculate value
   {        
     //--- initializing OpenCL objects
     if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
     {
        Print("OpenCL not found: ", GetLastError() );
        return(0);
     }

     string str;     
     if((cl_prg=CLProgramCreate(cl_ctx,cl_src,str))==INVALID_HANDLE)
     {
        CLContextFree(  cl_ctx ); Print("OpenCL program create failed: ", str);
        return(0);
     }

     if((cl_krn=CLKernelCreate(cl_prg,"Calculation"))==INVALID_HANDLE)
     {
        CLProgramFree(  cl_prg );
        CLContextFree(  cl_ctx ); Print("OpenCL kernel create failed");
        return(0);
     }

     if((cl_mem=CLBufferCreate(cl_ctx,SIZE_X*SIZE_Y*sizeof(int),CL_MEM_READ_WRITE))==INVALID_HANDLE)
     {
        CLKernelFree(   cl_krn );
        CLProgramFree(  cl_prg );
        CLContextFree(  cl_ctx ); Print("OpenCL buffer create failed");
        return(0);
     }

     int  offset[2]={0,0};
     int  work  [2]={SIZE_X,SIZE_Y};

     CLSetKernelArg(    cl_krn, 0, period );
     CLSetKernelArg(    cl_krn, 1, (float) price[position] );
     CLSetKernelArg(    cl_krn, 2, (float)prev_value );
     CLSetKernelArgMem( cl_krn, 3, cl_mem );

     Print( period, "  ", price[position], "  ", prev_value );

     //--- rendering the frame
     CLExecute(         cl_krn, 2, offset, work );
     CLBufferRead(      cl_mem, result );

     ArrayPrint( result );

     CLBufferFree(      cl_mem );
     CLKernelFree(      cl_krn );
     CLProgramFree(     cl_prg );
     CLContextFree(     cl_ctx );
  }
  //---
  return( result[0] );
}

This is the cl_src:

const string cl_src= 

"__kernel void Calculation(int period,                            \r\n"
                           "float price,                          \r\n"
                           "float prev_value,                     \r\n"
                           "__global float *result)               \r\n"
"{                                                                \r\n"
"   float pr=2.0/(period+1.0);                                    \r\n"
"   printf(\"Functional value: %f\",price);                       \r\n"
"   result[0]=price*pr+prev_value*(1-pr);                         \r\n"
"}                                                                \r\n";

The output expected is the value of the Exponential Moving average which must be some value after process. But in the output I am getting the value as 0.0000.

Which is not the expected value.

Even the printf() function in the cl_src not giving the output. My guess is that the value is not received by the process. I don't understand what I have missed.
Kindly, suggest me what I can do. Or is there anything I did in memory management? How I can make it multiple core workable??

1

1 Answers

1
votes

OpenCL-kernel, the very same as CUDA/GPU-kernel, code is compiled and transferred and "remotely" executed there - inside the OpenCL-device. So, unless some platform-specific tricks are present as an OpenCL-driver extension, there is no way to make the "remote"-execution engine "deliver"-printf()-output(s) back into the principally dis-connected / de-synchronised asynchronous heterogeneous distributed computing ecosystem ( the MetaTrader Terminal platform has nothing to do with the "remote" process-flow and vice-versa ).

 if (  INVALID_HANDLE == ( cl_prg = CLProgramCreate( cl_ctx,
                                                     cl_src,
                                                     str
                                                     )
                           )
       )
  {                        Print( "CLProgramCreate() failed: ", str );
                                   CLContextFree( cl_ctx );
                           return( 0 );
  }
  Print( "DEBUG[OpenCL]: compiler log:\nDEBUG[OpenCL]INFO:[[", str, "]]\n" );
  ...

So, better avoid any in-kernel "printing" unless platform-validated tools available

Next the interfacing: OpenCL / MQL5 inter-operability is documented to use exclusively the buffer-mapped tools for moving data-in and returning data-out.


The best next step:

Re-compile the simplified OpenCL kernel without any printing and re-test the simplest ever step: move just a plain simple value ( using as simple value as -1. ) into a single array cell, so as to validate the workflow and all the call-signature matches first, before moving into more details, ok?

const string
cl_src = "__kernel void Calculation(          int    period,     \r\n" // [0]__GPU_call-interface_ORDINAL
         "                                    float  price,      \r\n" // [1]__GPU_call-interface_ORDINAL
         "                                    float  prev_value, \r\n" // [2]__GPU_call-interface_ORDINAL
         "                           __global float *result      \r\n" // [3]__GPU_call-interface_ORDINAL
         "                           )                           \r\n"
         "{                                                      \r\n"
         "     result[0] = -1;                                   \r\n"
         "}                                                      \r\n";

...                                                               // OpenCL SETUP
// -----------------------------------------------<ASYNC>.LAUNCHER
CLExecute(         cl_krn, 2, offset, work );
// -----------------------------------------------<ASYNC>.MONITOR
do
while ( getOpenCL_KernelExecutionSTATE( cl_krn ) >     CL_COMPLETE );
// -----------------------------------------------<ASYNC>.COMPLETE
CLBufferRead(      cl_mem, result );
// -----------------------------------------------<ASYNC>.TRY-READ-MAPPING-BUFFER

int getOpenCL_KernelExecutionSTATE(                 int aKernelHANDLE = 0 )
{   int    cl_KernelExecutionSTATE = CLExecutionStatus( aKernelHANDLE );
    switch(cl_KernelExecutionSTATE )
    { 
      case( CL_COMPLETE  ): Print( "DEBUG[OpenCL]:program[, aKernelHANDLE, "] complete." );
                            return( CL_COMPLETE );

      case( CL_RUNNING   ): Print( "DEBUG[OpenCL]:program[, aKernelHANDLE, "] in running phase." );
                            return( CL_RUNNING );

      case( CL_SUBMITTED ): Print( "DEBUG[OpenCL]:program[, aKernelHANDLE, "] submitted for execution." );
                            return( CL_SUBMITTED );

      case( CL_QUEUED    ): Print( "DEBUG[OpenCL]:program[, aKernelHANDLE, "] waiting in a queue." );
                            return( CL_QUEUED );

      case( WRONG_VALUE  ): Print( "DEBUG[OpenCL]:program[, aKernelHANDLE, "] returned Error upon last CLExecutionStatus() call." );
                            return( WRONG_VALUE );

      default:              Print( "Ought never get here... Check updated MQL5 documentation." );
                            return( WRONG_VALUE );
    }
}