MQL5错误中的数组访问无效

时间:2018-04-02 13:14:11

标签: opencl mql5 metatrader5

我正在尝试访问数组,通过调用签名传递到系统调用的OnCalculation()事件处理程序中。

这就是它的写作方式:

    int OnCalculate(const int       rates_total,
                    const int       prev_calculated,
                    const datetime &time[],
                    const double   &open[],
                    const double   &high[],
                    const double   &low[],
                    const double   &close[],
                    const long     &tick_volume[],
                    const long     &volume[],
                    const int      &spread[]
                    )
    {
    /* The rest code is written here
       ...
    */
    }

我正在尝试将代码与OpenCL函数合并,以便程序使用GPU进行大量计算。但问题是当我试图将值从OnCalculation()传递给内核执行时,我收到错误。请参阅以下代码OnCalculation()

  CLSetKernelArg( cl_krn, 0, start );
  CLSetKernelArg( cl_krn, 1, rates_total );
  CLSetKernelArg( cl_krn, 2, time );
  CLSetKernelArg( cl_krn, 3, high );
  CLSetKernelArg( cl_krn, 4, low );

收到以下错误:

  

'time' - invalid array access ADX.mq5 285 31
    'high' - invalid array access ADX.mq5 286 31
     'low' - invalid array access ADX.mq5 287 31

我不知道为什么会出现这个问题。我无法从OnCalculation()传递数组。

请帮助我,我能做些什么?

1 个答案:

答案 0 :(得分:1)

在此处引用MQL5 array[]对象

是不可能的

OpenCL启动了一个全新的代码执行生态系统,MQL5端数据必须在那里正确“转移”......

使用模拟琐碎的GPU内核,使接收到的数组加倍:

const string                                                           //  by default some GPU doesn't support doubles
cl_SOURCE = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable      \r\n" //   cl_khr_fp64 directive is used to enable work with doubles
            "                                                   \r\n"
            "__kernel void Test_GPU( __global double *data,     \r\n" // [0]____GPU-kernel-side_CALL-SIGNATURE
            "                          const  int     N,        \r\n" // [1]____GPU-kernel-side_CALL-SIGNATURE
            "                          const  int     N_arrays  \r\n" // [2]____GPU-kernel-side_CALL-SIGNATURE
            "                          )                        \r\n"
            "{                                                  \r\n"
            "   uint kernel_index = get_global_id( 0 );         \r\n"
            "   if ( kernel_index > N_arrays ) return;          \r\n"
            "                                                   \r\n"
            "   uint local_start_offset = kernel_index * N;     \r\n"
            "   for (  int i = 0; i <  N; i++ )                 \r\n"
            "         data[i+local_start_offset] *= 2.0;        \r\n"
            "}                                                  \r\n";

// AFTER FIRST TESTING THE OpenCL DEVICES & THEIR CAPABILITIES ... ( see prev. posts )

#define ARRAY_SIZE   100  // size of the array
#define TOTAL_ARRAYS 5    // total arrays

// ONE CAN:
//---  SET OpenCL-specific handles' holders
int   cl_CONTEXT,  // an OpenCL-Context handle
      cl_PROGRAM,  // an OpenCL-Program handle
      cl_KERNEL,   // an OpenCL Device-Kernel handle
      cl_BUFFER;   // an OpenCL-buffer handle

uint  cl_offset[] = { 0 };            //--- prepare CLExecute() params
uint  cl_work[]   = { TOTAL_ARRAYS }; //--- global work size

double       DataArray2[];            //--- global mapping-object for data aimed to reach the GPU
ArrayResize( DataArray2,              //--- size it to fit data in
             ARRAY_SIZE * TOTAL_ARRAYS
             );
for ( int j = 0; j <  TOTAL_ARRAYS; j++ ) //--- fill mapped-arrays with data
{    uint local_offset = j * ARRAY_SIZE;               //--- set local start offset for j-th array
     for (  int i = 0; i <  ARRAY_SIZE; i++ )          //--- for j-th array
            DataArray2[i+local_offset] = MathCos(i+j); //--- fill array with some data
}

MQL5 / OpenCL设置的主要结构与此类似:

//--- INIT OpenCL 
   if ( INVALID_HANDLE == ( cl_CONTEXT = CLContextCreate() ) )
   {                        Print( "EXC: CLContextCreate() error = ", GetLastError() );
                            return( 1 ); // ---------------^ EXC/RET
   }
//--- NEXT create OpenCL program
   if ( INVALID_HANDLE == ( cl_PROGRAM = CLProgramCreate( cl_CONTEXT,
                                                          cl_SOURCE
                                                          )
                            )
        )
   {                        Print( "EXC: CLProgrameCreate() error = ", GetLastError() );
                            CLContextFree( cl_CONTEXT );
                            return( 1 ); // ----------------^ EXC/RET
   }
//--- NEXT create OpenCL kernel
   if ( INVALID_HANDLE == ( cl_KERNEL = CLKernelCreate( cl_PROGRAM,
                                                       "Test_GPU"
                                                        )
                            )
        )
   {                        Print( "EXC: CLKernelCreate() error = ", GetLastError() );
                            CLProgramFree( cl_PROGRAM );
                            CLContextFree( cl_CONTEXT ); 
                            return( 1 ); // --------------^ EXC/RET 
   }
//---  TRY: create an OpenCL cl_BUFFER object mapping
   if (  INVALID_HANDLE == ( cl_BUFFER = CLBufferCreate( cl_CONTEXT,
                                                         (uint) ( ARRAY_SIZE * TOTAL_ARRAYS * sizeof( double ),
                                                         CL_MEM_READ_WRITE
                                                         )
                             )
         )
   {                         Print( "EXC: CLBufferCreate() error == ", GetLastError() );
                             CLKernelFree(  cl_KERNEL  );
                             CLProgramFree( cl_PROGRAM );
                             CLContextFree( cl_CONTEXT ); 
                             return(1); // ----------------^ EXC/RET
   }
//--- NEXT: set OpenCL cl_KERNEL GPU-side-kernel call-parameters
   CLSetKernelArgMem( cl_KERNEL, 0, cl_BUFFER    ); // [0]____GPU-kernel-side_CALL-SIGNATURE
   CLSetKernelArg(    cl_KERNEL, 1, ARRAY_SIZE   ); // [1]____GPU-kernel-side_CALL-SIGNATURE
   CLSetKernelArg(    cl_KERNEL, 2, TOTAL_ARRAYS ); // [2]____GPU-kernel-side_CALL-SIGNATURE

//--- NEXT: write data into to OpenCL cl_BUFFER mapping-object
   CLBufferWrite( cl_BUFFER,
                  DataArray2
                  );

//---  MAY execute OpenCL kernel
   CLExecute( cl_KERNEL, 1, cl_offset, cl_work );

//---  MAY read data back, from OpenCL cl_BUFFER mapping-object
   CLBufferRead(  cl_BUFFER, DataArray2 );

   CLBufferFree(  cl_BUFFER  ); //--- FINALLY free OpenCL buffer cl_BUFFER mapping-object
   CLKernelFree(  cl_KERNEL  ); //--- FINALLY free OpenCL kernel object
   CLProgramFree( cl_PROGRAM ); //--- FINALLY free OpenCL programme object / handle
   CLContextFree( cl_CONTEXT ); //--- FINALLY free OpenCL cl_CONTEXT object / handle