Ecco cosa si può fare con OpenCL direttamente in MetaTrader 5 senza alcuna DLL - pagina 18

 
Aleksei Grebenkin:

Renat Fatkhullin come faccio a contattarti per discutere la possibilità di scrivere in MQL5+OpenCL. ho bisogno di utilizzare la potenza di elaborazione delle schede video. se ho capito bene, quindi utilizzando un esempio dalla pratica: il robot scritto ottimizza solo 11 parametri da 3 macchine collegate a una rete locale, il periodo è solo 1 anno 6 ore. ho provato a caricare 5 anni di ottimizzazione con una ricerca completa di dati, mi ha mostrato che 2 mesi devono aspettare.Se ho capito bene, OpenCL risolverà il problema. La velocità dovrebbe aumentare di centinaia di volte, dato che i calcoli non coinvolgeranno i processori ma le schede video. Significa che prendendo in considerazione l'intero sistema di trading, si avranno circa 200-300 parametri nelle impostazioni.

I calcoli OpenCL non sono coinvolti nella parallelizzazione del processo di ottimizzazione.

Con OpenCL, è possibile calcolare una parte specifica dell'algoritmo più velocemente e in parallelo. Abbiamo molti articoli e discussioni su OpenCL.

 
Maxim Kuznetsov #:

Cosa ti impedisce di comprare una carta più grande?

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

È stato detto e fatto.




Accelerazione X2-X3 dai calcoli precedenti su Gforce RTX2080 TI

Ma c'è un punto a parte per chi sta testando modelli di reti neurali nel tester.

OpenCl non permette l'accesso multi-thread se ci sono più di 10-12 processi (agenti).

Soprattutto se più reti neurali sono create simultaneamente per analizzare diversi dati con una fusione in uno.

E nonostante il fatto che il server abbia ora 96 processori logici, è ancora necessario usarne 12.

Quindi è più redditizio avere diversi vecchi computer della rete, probabilmente più economico di molte volte.


Separatamente, vorrei menzionare un'opportunità separata per installare AMD SDK che ha permesso di utilizzare le CPU con OpenCL.

Ora, ci sono 96 dispositivi pronti a svolgere un compito alla stessa velocità, ma non dipendono solo dalla potenza della scheda.



Tuttavia, la libreria OpenCl ha dovuto essere corretta perché il processo di selezione dei dispositivi

CLContextCreate(CL_USE_ANY)

non permette di capire quale dispositivo è attualmente caricato.

E selezionare solo GPU o solo CPU non permette di usare entrambe le opzioni allo stesso tempo.


Per risolvere questo problema ho fatto un test di ogni scheda per la velocità di calcolo attuale,

usando questo interessante esempio per simulare il calcolo (bello)

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


Nel codice della libreria è incarnato in questo modo

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

nel codice EA

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

Nella libreria OpenCL, tenete conto della possibilità di selezionare il 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);     
         }
 

Nel rilascio di domani rilasceremo dei tipi di dati matriciali/vettoriali interni da usare nell'apprendimento automatico.

Il codice dei programmi MQL5 diventerà molto più semplice e ci permetterà di implementare un grande insieme di operazioni matematiche.

Questa è la prima generazione di funzionalità e poi implementeremo meccanismi più complessi per implementare le capacità di pacchetti come TensorFlow. OpenCL sarà utile per questo.

 
Che senso ha tutto questo multithreading per una rete neurale quando un passaggio di una nuova epoca deve basarsi sui risultati di un passaggio precedente. E tutti i thread paralleli ripeteranno solo i risultati del primo. E alla fine depositeranno i risultati in un unico file. Sovrascrivendo i risultati del thread precedente ma in sostanza senza cambiare il valore...
 
Dmytryi Voitukhov #:
Che senso ha tutto questo multithreading per una rete neurale, quando il passaggio di una nuova epoca dovrebbe essere basato sui risultati del passaggio precedente. E tutti i thread paralleli ripeteranno solo i risultati del primo. E alla fine depositeranno i risultati in un unico file. Sovrascrivendo i risultati del thread precedente ma in sostanza senza cambiare il valore...

Renat esclama e tu piagnucoli. Quanti anni hai?

 

Leggermente corretta la biblioteca, resa più bella

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