Eis o que você pode fazer com OpenCL diretamente no MetaTrader 5 sem DLLs - página 18

 
Aleksei Grebenkin:

Renat Fatkhullin como posso entrar em contato com você para discutir a possibilidade de escrever em MQL5+OpenCL. eu preciso usar o poder de processamento das placas de vídeo. se entendi corretamente, então usando um exemplo da prática: o robô escrito otimiza apenas 11 parâmetros por 3 máquinas conectadas a uma rede local, o período é de apenas 1 ano e 6 horas. eu tentei cobrar 5 anos para otimização com uma pesquisa completa dos dados, isso me mostrou que 2 meses têm que esperar.Se eu entendi corretamente, o OpenCL resolverá o problema. A velocidade deve aumentar centenas de vezes, já que os cálculos não envolverão processadores, mas placas de vídeo. Isso significa que, levando em conta todo o sistema comercial, você terá cerca de 200-300 parâmetros em configurações.

Os cálculos do OpenCL não estão envolvidos na paralelização do processo de otimização.

Com o OpenCL, você pode calcular uma parte específica do algoritmo mais rapidamente e em paralelo. Temos muitos artigos e discussões sobre OpenCL.

 
Maxim Kuznetsov #:

O que está impedindo você de comprar um cartão maior?

algumas A100https://www.nvidia.com/ru-ru/data-center/a100/

Já foi dito e feito.




X2-X3 aceleração dos cálculos anteriores na Gforce RTX2080 TI

Mas há um ponto separado para qualquer pessoa que esteja testando modelos de redes neurais no testador.

OpenCl não permite o acesso multi-tarefa se houver mais de 10-12 processos (agentes).

Especialmente se múltiplas redes neurais forem criadas simultaneamente para analisar dados diferentes com uma fusão em uma só.

E apesar do fato de que o servidor agora tem 96 processadores lógicos, ainda temos que usar 12.

Portanto, é mais rentável ter vários computadores antigos da rede, provavelmente mais baratos por muitas vezes.


Separadamente, eu gostaria de mencionar uma oportunidade separada para instalar o AMD SDK que permitiu o uso de CPUs com OpenCL.

Agora, existem 96 dispositivos prontos para realizar uma tarefa na mesma velocidade, mas não dependendo apenas da potência do cartão.



Entretanto, a biblioteca OpenCl teve que ser corrigida porque o processo de seleção do dispositivo

CLContextCreate(CL_USE_ANY)

não permite entender qual dispositivo está atualmente carregado.

E selecionar apenas GPU ou apenas CPU não permite usar ambas as opções ao mesmo tempo.


Para resolver este problema, fiz um teste de cada cartão para a velocidade de computação atual,

usando este interessante exemplo para simular o cálculo (legal)

https://www.mql5.com/ru/code/825


No código da biblioteca, ela é encarnada da seguinte forma

int COpenCL::ID_FasterDevice()
  {
 
   int cl_prg;
   int cl_krn;
   int cl_mem;
   int cl_ctx;
   string device;
   ulong speed [];
   
   int dCount= (int)CLGetInfoInteger(0,CL_DEVICE_COUNT);
  
   
   if (dCount>1)
   {
   ArrayResize(speed,dCount);
   
      //----------------- измерим текщую производительность и выберем более быстрый девайс ----------
      for(int i = 0; i<dCount;i++)
         {
         cl_ctx=i;
         CLGetInfoString(cl_ctx,CL_DEVICE_NAME,device);
         Print(cl_ctx,": ",device);
         ulong start_time=GetMicrosecondCount();
     
//--- initializing OpenCL objects
   if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
     {
      Print("OpenCL not found");
      return -1;
     }
   if((cl_prg=CLProgramCreate(cl_ctx,cl_src))==INVALID_HANDLE)
     {
      CLContextFree(cl_ctx);
      Print("OpenCL program create failed");
      return -1;
     }
   if((cl_krn=CLKernelCreate(cl_prg,"MFractal"))==INVALID_HANDLE)
     {
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("OpenCL kernel create failed");
      return -1;
     }
   if((cl_mem=CLBufferCreate(cl_ctx,SIZE_X*SIZE_Y*sizeof(uint),CL_MEM_READ_WRITE))==INVALID_HANDLE)
     {
      CLKernelFree(cl_krn);
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("OpenCL buffer create failed");
      return -1;
     }
//--- getting ready for execution
   float x0       =-2;
   float y0       =-0.5;
   float x1       =-1;
   float y1       = 0.5;
   uint  max      = 20000;
   uint  offset[2]={0,0};
   uint  work  [2]={SIZE_X,SIZE_Y};
   string objname ="OpenCL_"+IntegerToString(ChartID());
   string resname ="::Mandelbrot_"+IntegerToString(ChartID());
//--- setting unchangeable OpenCL function parameters
   CLSetKernelArg(cl_krn,4,max);
   CLSetKernelArgMem(cl_krn,5,cl_mem);
//--- creating the object for graphics display
   ChartRedraw();
   Comment("Benchmark OpenCl devices");
   ObjectCreate(0,objname,OBJ_BITMAP_LABEL,0,0,0);
   ObjectSetInteger(0,objname,OBJPROP_XDISTANCE,4);
   ObjectSetInteger(0,objname,OBJPROP_YDISTANCE,26);
//--- create initial empty picture
   uint buf[];

   ArrayResize(buf,SIZE_X*SIZE_Y);
   ResourceCreate(resname,buf,SIZE_X,SIZE_Y,0,0,SIZE_X,COLOR_FORMAT_XRGB_NOALPHA);
   ObjectSetString(0,objname,OBJPROP_BMPFILE,resname);
//--- rendering, till we are not stopped from the outside
   for (int samples=0;samples<100;samples++)
     {
      uint x=GetTickCount();
      //--- setting floating parameters
      CLSetKernelArg(cl_krn,0,x0);
      CLSetKernelArg(cl_krn,1,y0);
      CLSetKernelArg(cl_krn,2,x1);
      CLSetKernelArg(cl_krn,3,y1);
      //--- rendering the frame
      CLExecute(cl_krn,2,offset,work);
      //--- taking the frame data
      CLBufferRead(cl_mem,buf);
      //--- outputting the rendering time
      Comment(IntegerToString(GetTickCount()-x)+" msec per frame");
      //--- saving the frame in memory and drawing it
      ResourceCreate(resname,buf,SIZE_X,SIZE_Y,0,0,SIZE_X,COLOR_FORMAT_XRGB_NOALPHA);
      ChartRedraw();
      //--- a small pause and parameters update for the next frame
      Sleep(10);
      x0+=0.001 f;
      x1-=0.001 f;
      y0+=0.001 f;
      y1-=0.001 f;
     
     }
//--- removing OpenCL objects
   CLBufferFree(cl_mem);
   CLKernelFree(cl_krn);
   
   CLProgramFree(cl_prg);
   CLContextFree(cl_ctx);
         ulong finishtime=GetMicrosecondCount();
         ulong testtime= finishtime-start_time;  
         speed [i] = testtime; 
         
   ObjectDelete(0,objname);
   Comment("");
     }
      
      m_context= ArrayMinimum(speed,0,WHOLE_ARRAY);
   }
   else 
      m_context=-1;
//--- remove object
  
   return m_context;
  }
//+------------------------------------------------------------------+

no código EA

 COpenCL         *TestOpenCL;
      TestOpenCL =new COpenCL;
      int faster_device=TestOpenCL.ID_FasterDevice();
      TestOpenCL.Initialize(cl_program,id_device,true);         

Na biblioteca do OpenCL, levar em conta a possibilidade de selecionar o dispositivo

//+------------------------------------------------------------------+
//| Initialize                                                       |
//+------------------------------------------------------------------+
bool COpenCL::Initialize(const string program,const int id_device=-1,const bool show_log=true)
  {  
   
     
     m_context=id_device;
    
     if((m_context=CLContextCreate())==INVALID_HANDLE)
     {
      Print("OpenCL not found");      
     }   
     else if ((m_context=CLContextCreate(CL_USE_ANY))==INVALID_HANDLE)
         {
       
               Print("OpenCL not found. Error code=",GetLastError());
                  return(false);     
         }
Arquivos anexados:
 

No lançamento de amanhã estamos lançando tipos de dados de matriz/vetor internos para uso no aprendizado de máquinas.

O código dos programas MQL5 se tornará muito mais simples e nos permitirá implementar um grande conjunto de operações matemáticas.

Esta é a primeira geração de funcionalidades e então implementaremos mecanismos mais complexos para implementar as capacidades de pacotes como o TensorFlow. O OpenCL virá a calhar para isso.

 
Para que serve toda essa multi-tarefa para uma rede neural quando uma passagem de uma nova época deve se basear nos resultados de uma passagem anterior. E todos os fios paralelos só repetirão os resultados do primeiro. E no final, eles depositarão os resultados em um único arquivo. Sobrescrevendo os resultados do segmento anterior, mas em essência sem alterar o valor...
 
Dmytryi Voitukhov #:
Qual é o objetivo de toda essa multi-tarefa para uma rede neural, quando uma passagem de uma nova época deve ser baseada nos resultados da passagem anterior. E todos os fios paralelos só repetirão os resultados do primeiro. E no final, eles depositarão os resultados em um único arquivo. Sobrescrevendo os resultados do segmento anterior, mas em essência sem alterar o valor...

Renat exclama e você se lamenta. Quantos anos você tem?

 

Um pouco de afinação à biblioteca, feita à beleza da mesma

       double testtime= (GetTickCount()-start_time)/1000;  
         speed [i] = NormalizeDouble(MathRound(1000/testtime/8)*8,3); //NormalizeDouble(1000/testtime,2); 
      
      CLGetInfoString(i,CL_DEVICE_NAME,device);
       Print("Device #", i,", speed =",speed [i]," FPS. ",device); 
   ObjectDelete(0,objname);
   Comment("");
     }
      
      m_context= ArrayMaximum(speed,0,WHOLE_ARRAY);
      CLGetInfoString(m_context,CL_DEVICE_NAME,device);
     
      Print("Faster device: #",m_context,", ",device," "); 


Arquivos anexados: