Voici ce que vous pouvez faire avec OpenCL directement dans MetaTrader 5, sans aucune DLL. - page 18

 
Aleksei Grebenkin:

Renat Fatkhullin comment puis-je vous contacter pour discuter de la possibilité d'écrire en MQL5+OpenCL. j'ai besoin d'utiliser la puissance de traitement des cartes vidéo. si je comprends bien, alors en utilisant un exemple de la pratique : le robot écrit optimise seulement 11 paramètres par 3 machines connectées via le réseau local, la période est seulement 1 an 6 heures. j'ai essayé de charger 5 ans d'optimisation avec une recherche complète de données, il m'a montré que 2 mois doivent attendre.Si j'ai bien compris, OpenCL va résoudre le problème. La vitesse devrait être multipliée par des centaines de fois, puisque les calculs ne feront pas intervenir des processeurs mais des cartes vidéo. Cela signifie que si l'on prend en compte l'ensemble du système de trading, il y aura environ 200 à 300 paramètres dans les réglages.

Les calculs OpenCL ne sont pas impliqués dans la parallélisation du processus d'optimisation.

Avec OpenCL, vous pouvez calculer une partie spécifique de l'algorithme plus rapidement et en parallèle. Nous avons de nombreux articles et discussions sur OpenCL.

 
Maxim Kuznetsov #:

Qu'est-ce qui vous empêche d'acheter une carte plus grande ?

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

C'est dit et fait.




Accélération X2-X3 des calculs précédents sur Gforce RTX2080 TI

Mais il y a un point distinct pour tous ceux qui testent des modèles de réseaux neuronaux dans le testeur.

OpenCl ne permet pas l'accès multithread s'il y a plus de 10-12 processus (agents).

Surtout si plusieurs réseaux neuronaux sont créés simultanément pour analyser différentes données avec une fusion en une seule.

Et malgré le fait que le serveur possède maintenant 96 processeurs logiques, nous devons toujours en utiliser 12.

Il est donc plus rentable de retirer plusieurs vieux ordinateurs du réseau, ce qui est probablement plusieurs fois moins cher.


Par ailleurs, je voudrais mentionner une opportunité distincte d'installer le SDK AMD qui permettait d'utiliser les CPU avec OpenCL.

Désormais, il existe 96 appareils prêts à effectuer une tâche à la même vitesse, mais ne dépendant pas uniquement de la puissance de la carte.



Cependant, la bibliothèque OpenCl a dû être corrigée car le processus de sélection des périphériques

CLContextCreate(CL_USE_ANY)

ne permet pas de comprendre quel dispositif est actuellement chargé.

Et le fait de sélectionner GPU uniquement ou CPU uniquement ne permet pas d'utiliser les deux options en même temps.


Pour résoudre ce problème j'ai fait un test de chaque carte pour la vitesse de calcul actuelle,

utiliser cet exemple intéressant pour simuler le calcul (sympa)

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


Dans le code de la bibliothèque, il se présente comme suit

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

dans le code de l'EA

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

Dans la bibliothèque OpenCL, tenez compte de la possibilité de sélectionner le périphérique

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

Dans la version de demain, nous publierons des types de données matricielles/vectorielles internes pour une utilisation dans l'apprentissage automatique.

Le code des programmes MQL5 deviendra beaucoup plus simple et nous permettra d'implémenter un large ensemble d'opérations mathématiques.

Il s'agit de la première génération de fonctionnalités. Nous mettrons ensuite en place des mécanismes plus complexes pour mettre en œuvre les capacités de paquets tels que TensorFlow. OpenCL sera très utile pour cela.

 
Quel est l'intérêt de tout ce multithreading pour un réseau neuronal quand le passage d'une nouvelle époque doit s'appuyer sur les résultats d'un passage précédent. Et tous les fils parallèles ne feront que répéter les résultats du premier. Et à la fin, ils déposeront les résultats dans un seul fichier. En écrasant les résultats du fil précédent, mais en substance sans changer la valeur...
 
Dmytryi Voitukhov #:
Quel est l'intérêt de tout ce multithreading pour un réseau neuronal, alors que le passage d'une nouvelle époque devrait être basé sur les résultats du passage précédent. Et tous les fils parallèles ne feront que répéter les résultats du premier. Et à la fin, ils déposeront les résultats dans un seul fichier. En écrasant les résultats du fil précédent, mais en substance sans changer la valeur...

Renat s'exclame et vous gémissez. Quel âge avez-vous ?

 

Un peu d'ajustement à la bibliothèque, fait pour la beauté de celle-ci

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


Dossiers :