La tela è forte! - pagina 19

 
Renat Fatkhullin:

Si scopre che stavo guardando la frequenza di generazione del web, non la frequenza di uscita.

Sono numeri diversi, multipli l'uno dell'altro.

Ho scoperto che stavo calcolando la frequenza di generazione del web (senza uscita) e la frequenza di uscita (senza generazione) un po' male

Ecco una versione più corretta.


Risultati sul mio processore:

Se si prende il tempo puramente generando un fotogramma di 200 cerchi lisciati senza uscita, avviene a circa 500 fotogrammi al secondo.

formando un fotogramma di 200 cerchi non smussati senza uscita - circa 1000 fps.

La frequenza dell'uscita dell'immagine (tela) stessa (funzione Update) è di circa 650 fotogrammi al secondo.

Hai davvero lavorato sodo!

File:
 
Renat Fatkhullin:

Attenzione alle conversioni di massa dei tipi (int)double o (double)int e al mischiare int+double nelle operazioni mat in generale.

Questo dà l'overhead più selvaggio al processore - proprio un comando assembler così costoso. Se contate in doppio, continuate a contare in doppio e non passate ai tipi interi.

Comandi come cvtsi2sd/cvttsd2si sono molto lunghi. Un piccolo suggerimento nell'articolo"L'istruzione x86 più lenta", villano numero 2.

Grazie per un articolo molto prezioso.


Ma ad essere onesti, non capisco perché allora in questo semplice script:

#define  Num 1000000 
void OnStart()
  {
    double arr[Num];
    for (int i=0;i<Num;i++) arr[i]=(double) rand()/(1+rand()%100); // инициализируем массив случайными числами double от 0.0 до 32767.0
    
    long sumL=0;
    
    ulong t1=GetMicrosecondCount();
    for (int i=0;i<Num;i++) sumL+=(long)arr[i]; // сумма long
    t1=GetMicrosecondCount()-t1;
    
    double sumD=0;
    
    ulong t2=GetMicrosecondCount();
    for (int i=0;i<Num;i++) sumD+=arr[i];      // сумма double
    t2=GetMicrosecondCount()-t2;  
    
    Print ("Сумма long   = "+ string(sumL)+ ", время суммирования "+string(t1)+" микросекунд");
    Print ("Сумма double = "+ DoubleToString(sumD)+ ", время суммирования "+string(t2)+" микросекунд");   
  }

la somma di long con la conversione del tipo double in long è molto più veloce della somma di double dello stesso array senza conversione

2019.01.15 22:21:46.410 TestSpeedDoubleAndInt (NZDUSD,M5)       Сумма long   = 849290923,          время суммирования 748  микросекунд
2019.01.15 22:21:46.410 TestSpeedDoubleAndInt (NZDUSD,M5)       Сумма double = 849764484.23059070, время суммирования 1393 микросекунд
 

In primo luogo, si dovrebbe guardare il codice assembly e il risultato delle ottimizzazioni di casi estremamente semplici (la supermicrosintesi è stata a lungo fuorviante). È facile imbattersi in un caso ideale di implementazione del trasportatore.

In secondo luogo, quasi nessuno può garantire come questo o quel codice verrà compilato e quanto tempo impiegherà per essere eseguito.

Basta aggiungere una riga/comando in più nel codice e la velocità cambia drasticamente. Il vero codice/dati potrebbe anche uscire dalla cache L1/L2 e basta.

Come ha funzionato per voi? In teoria/super-sintesi sembra che i comandi interi aiutino nella velocità, ma nel codice reale è un salasso. Perché c'è decine/centinaia di volte più codice, nessuna convezione, salti costanti da calcoli interi a reali e l'ottimizzazione è limitata.

 
Renat Fatkhullin:


Perché l'inizializzazione degli array di qualsiasi tipo in MQL4 è più di 10 volte più lenta che in MQL5?

 
Реter Konow:

Perché l'inizializzazione degli array di qualsiasi tipo in MQL4 è più di 10 volte più lenta che in MQL5?

Perché lì tutti gli array sono dinamici e il linguaggio è dieci volte più lento.

 
Questa è una bella risposta)).
Dieci volte più lento perché dieci volte più lento)).
 

Un indicatore ultra-veloce di centinaia di medie mobili, implementato su Canvas.

100 linee MA (periodo passo 10) - tempo di calcolo e visualizzazione sullo schermo - 4-7 millisecondi


1000 linee MA (periodo passo 1) - tempo di calcolo e visualizzazione - 20-30 millisecondi.


Non ho testato troppo il codice. Ci possono essere dei bug. Implementato solo per le barre spesse un pixel (è forzato a questa scala). Anche la frequenza di aggiornamento dello schermo non è ottimizzata. Tutte le linee sono calcolate e completamente emesse ad ogni tick.

#include <Canvas\iCanvas.mqh> //https://www.mql5.com/ru/code/22164
#property indicator_chart_window

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
input int MA=1000;   // максимальный период скользящих средних
input int stepMa=10; // шаг скользящих средних

double  Close[];
long Total;
int Ma;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
   ChartSetInteger(0,CHART_SCALE,0,0);
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CopyClose(_Symbol,_Period,(int)W.Right_bar,W.BarsInWind+Ma-1,Close);
   Total=SeriesInfoInteger(_Symbol,_Period,SERIES_BARS_COUNT);
   if (Total<(MA+W.BarsInWind)) Ma=(int)Total-1-W.BarsInWind; else Ma=MA;
   if (Ma<=0) Ma=1;
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[])
  {
   CopyClose(_Symbol,_Period,(int)W.Right_bar,W.BarsInWind+Ma-1,Close);
   Print("Время формирования кадра = "+(string)(nMA()/1000)+" миллискунд");
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id==CHARTEVENT_CHART_CHANGE)
     {
      ChartSetInteger(0,CHART_SCALE,0,0);
      CopyClose(_Symbol,_Period,(int)W.Right_bar,W.BarsInWind+Ma-1,Close);
      Print("Время формирования кадра = "+(string)(nMA()/1000)+" миллискунд");
     }
  }
//+------------------------------------------------------------------+

ulong nMA()
  {
   ulong t=GetMicrosecondCount();
   int preY=0;
   Canvas.Erase();
   double S=0;
   for(int i=0;i<Ma; i++) S+=Close[i];

   for(int Per=Ma;Per>0;)
     {
      double s=S;
      uint Clr=Grad((double)Per/Ma);
      for(int x=0; x<W.BarsInWind;x++)
        {
         int Y=(int)(Canvas.Y(s/Per)-0.5);
         if(x>0) if(fabs(Y-preY)>1) Canvas.Line(x-1,preY,x,Y,Clr);
         else Canvas.PixelSet(x,Y,Clr);
         if((Ma+x)<ArraySize(Close)) s=s-Close[x+Ma-Per]+Close[Ma+x]; else break;
         preY=Y;
        }
      for(int j=0; j<stepMa; j++) if(Per>0){ S=S-Close[Ma-Per]; Per--;} else break;
     }
   Canvas.Update();
   return GetMicrosecondCount()-t;
  }
//+------------------------------------------------------------------+
uint Grad(double p)
  {
   static uint Col[6]={0xFF0000FF,0xFFFF00FF,0xFFFF0000,0xFFFFFF00,0xFF00FF00,0xFF00FFFF};
   if(p>0.9999) return Col[5];
   if(p<0.0001) return Col[0];
   p=p*5;
   int n=(int)p;
   double k=p-n;
   argb c1,c2;
   c1.clr=Col[n];
   c2.clr=Col[n+1];
   return ARGB(255,c1.c[2]+uchar(k*(c2.c[2]-c1.c[2])+0.5),
                   c1.c[1]+uchar(k*(c2.c[1]-c1.c[1])+0.5),
                   c1.c[0]+uchar(k*(c2.c[0]-c1.c[0])+0.5));
  }
//+------------------------------------------------------------------+
File:
MultiMA.mq5  9 kb
 
Nikolai Semko:

Un indicatore ultra-veloce di centinaia di medie mobili, implementato su Canvas.

100 linee MA (periodo passo 10) - tempo di calcolo e visualizzazione sullo schermo - 4-7 millisecondi


1000 linee MA (periodo passo 1) - tempo per il calcolo e la visualizzazione - 20-30 millisecondi


figo, con gli indicatori standard tutto sarebbe morto

 
Maxim Dmitrievsky:

fresco, gli indicatori standard avrebbero appeso tutto.

e poi ci sarebbe un miglio di codice...

forse anche questo può essere fatto solo con un modello. Non conosco la limitazione del numero di linee di indicatori nel corpo di un indicatore.

 
Nikolai Semko:

...

Non sono a conoscenza della limitazione del numero di linee di indicatori nel corpo di un indicatore.

C'è un limite. Si possono fare fino a 512 buffer di indicatori >>>https://www.mql5.com/ru/docs/indicators

Документация по MQL5: Технические индикаторы
Документация по MQL5: Технические индикаторы
  • www.mql5.com
Все функции типа iMA, iAC, iMACD, iIchimoku и т.п., создают в глобальном кеше клиентского терминала копию соответствующего технического индикатора. Если копия индикатора с этими параметрами уже существует, то новая копия не создается, а увеличивается счетчик ссылок на данную копию. Эти функции возвращают хэндл соответствующей копии индикатора...