【问题标题】:Not getting the expected output from OpenCL-kernel in MQL5在 MQL5 中未从 OpenCL 内核获得预期输出
【发布时间】:2018-04-03 22:54:48
【问题描述】:

这是我正在尝试使用的功能:

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

这是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";

预期的输出是Exponential Moving average 的值,它必须是处理后的某个值。但在输出中,我得到的值为0.0000

这不是预期值。

即使是cl_src 中的 printf() 函数也没有给出输出。我的猜测是该过程未收到该值。我不明白我错过了什么。
请告诉我我能做什么。或者我在内存管理方面做了什么?我怎样才能让它多核可行??

【问题讨论】:

    标签: opencl mql5 metatrader5


    【解决方案1】:

    OpenCL-kernel,与 CUDA/GPU-kernel 非常相似,代码在 OpenCL 设备内部编译、传输和“远程”执行。因此,除非某些特定于平台的技巧作为 OpenCL 驱动程序扩展存在,否则无法使“远程”执行引擎“交付”-printf()-输出返回进入主要断开/去同步的异步异构分布式计算生态系统(MetaTrader 终端平台与“远程”流程无关,反之亦然)。

     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" );
      ...
    

    所以,最好避免任何内核“打印,除非有平台验证的工具可用

    接下来是接口:OpenCL / MQL5 互操作性被记录为专门使用 缓冲区 映射工具来移动数据和返回数据。 p>


    最好的下一步:

    无需任何打印即可重新编译简化的 OpenCL 内核并重新测试最简单的步骤:仅将一个普通的简单值(使用与 -1 一样的简单值)移动到单个数组单元中,以验证工作流程并且所有呼号都匹配,然后再进入更多细节,好吗?

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

    【讨论】:

    • 你能告诉我2offset' and work`在CLExecute( cl_krn, 2, offset, work );中是什么。实际上,当我在我的程序中使用它时,我得到的输出为零 (0) 意味着根本没有输出。但是当我忽略并只使用CLExecute(cl_krn); 时,程序运行良好并给出了输出。为什么我的程序不能使用 GPU 的多个核心?我不明白。
    • 是的,我可以。随意 [+1] 奖励并接受此和其他以前提供的有用且认真的答案,并可能会打开您选择的另一个问题。这就是 StackOverflow 的工作方式。在您的问题下确实有大量未获得奖励且尚未接受的答案是一个危险信号。
    • 是的,您的回答值得接受,但是当我在工作和偏移的帮助下运行程序时,我没有得到零作为输出的原因。没有变量,我得到了答案。
    猜你喜欢
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多