Esto es lo que puedes hacer con OpenCL directamente en MetaTrader 5 sin ninguna DLL - página 18

 
Aleksei Grebenkin:

Renat Fatkhullin como me pongo en contacto con usted para discutir la posibilidad de escribir en MQL5+OpenCL. necesito utilizar la potencia de procesamiento de las tarjetas de video. si entiendo bien, a continuación, utilizando un ejemplo de la práctica: el robot escrito optimiza sólo 11 parámetros por 3 máquinas conectadas a una red local, el período es sólo 1 año 6 horas. traté de cobrar 5 años para la optimización con una búsqueda completa de datos, me mostró que 2 meses tienen que esperar.Si he entendido bien, OpenCL solucionará el problema. La velocidad debería aumentar cientos de veces, ya que los cálculos no implicarán a los procesadores, sino a las tarjetas de vídeo. Esto significa que, teniendo en cuenta todo el sistema de comercio, tendrá alrededor de 200-300 parámetros en la configuración.

Los cálculos de OpenCL no intervienen en la paralelización del proceso de optimización.

Con OpenCL, se puede calcular una parte específica del algoritmo más rápidamente y en paralelo. Tenemos muchos artículos y debates sobre OpenCL.

 
Maxim Kuznetsov #:

¿Qué te impide comprar una tarjeta más grande?

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

Ya está dicho y hecho.




Aceleración X2-X3 de los cálculos anteriores en Gforce RTX2080 TI

Pero hay un punto aparte para quien pruebe modelos de redes neuronales en el probador.

OpenCl no permite el acceso multihilo si hay más de 10-12 procesos (agentes).

Especialmente si se crean múltiples redes neuronales simultáneamente para analizar diferentes datos con una fusión en uno.

Y a pesar de que el servidor tiene ahora 96 procesadores lógicos, tenemos que utilizar 12.

Por lo tanto, es más rentable tener varios ordenadores viejos de la red, probablemente más baratos por muchas veces.


Por otra parte, me gustaría mencionar una oportunidad separada para instalar el SDK de AMD que permitía utilizar CPUs con OpenCL.

Ahora, hay 96 dispositivos preparados para realizar una tarea a la misma velocidad, pero sin depender únicamente de la potencia de la tarjeta.



Sin embargo, la biblioteca OpenCl tuvo que ser corregida porque el proceso de selección de dispositivos

CLContextCreate(CL_USE_ANY)

no permite entender qué dispositivo está cargado actualmente.

Y la selección de sólo GPU o sólo CPU no permite utilizar ambas opciones al mismo tiempo.


Para resolver este problema, hice una prueba de cada tarjeta para la velocidad de cálculo actual,

utilizando este interesante ejemplo para simular la computación (agradable)

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


En el código de la biblioteca se plasma así

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;
  }
//+------------------------------------------------------------------+

en el código EA

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

En la biblioteca OpenCL, tenga en cuenta la posibilidad de seleccionar el 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);     
         }
Archivos adjuntos:
 

En la versión de mañana vamos a liberar tipos de datos matriciales/vectoriales internos para su uso en el aprendizaje automático.

El código de los programas MQL5 será mucho más sencillo y nos permitirá implementar un amplio conjunto de operaciones matemáticas.

Esta es la primera generación de funcionalidades y luego implementaremos mecanismos más complejos para implementar las capacidades de paquetes como TensorFlow. OpenCL será muy útil para esto.

 
De qué sirve todo este multithreading para una red neuronal cuando el paso de una nueva época debe basarse en los resultados de un paso anterior. Y todos los hilos paralelos sólo repetirán los resultados del primero. Y al final depositarán los resultados en un archivo. Sobrescribiendo los resultados del hilo anterior pero en esencia sin cambiar el valor...
 
Dmytryi Voitukhov #:
¿Qué sentido tiene todo este multithreading para una red neuronal, cuando el paso de una nueva época debería basarse en los resultados del paso anterior? Y todos los hilos paralelos sólo repetirán los resultados del primero. Y al final depositarán los resultados en un archivo. Sobrescribiendo los resultados del hilo anterior pero en esencia sin cambiar el valor...

Renat exclama y tú te quejas. ¿Qué edad tienes?

 

Un poco de ajuste a la biblioteca, hecho a la belleza de la misma

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


Archivos adjuntos:
 
Estos avances pueden ser beneficiosos para los desarrolladores que trabajan en aplicaciones de aprendizaje automático, ya que facilitarán la manipulación de datos y la implementación de algoritmos matemáticos, lo que podría acelerar el desarrollo de soluciones basadas en aprendizaje automático en el entorno MQL5.