El lienzo es genial. - página 19

 
Renat Fatkhullin:

Resulta que estaba mirando la frecuencia de generación de la red, no la frecuencia de salida.

Son números diferentes, múltiplos uno del otro.

Resulta que estaba calculando la frecuencia de generación de la web (sin salida) y la frecuencia de salida (sin generación) un poco mal

Esta es una versión más correcta.


Resultados en mi procesador:

Si se toma el tiempo puramente generando un fotograma de 200 círculos suavizados sin salida, ocurre a unos 500 fotogramas por segundo.

formando un fotograma de 200 círculos sin alisar y sin salida - unos 1000 fps.

La frecuencia de la propia salida de la imagen (lienzo) (función de actualización) es de unos 650 fps.

Has trabajado mucho.

Archivos adjuntos:
 
Renat Fatkhullin:

Cuidado con las conversiones masivas de tipos (int)double o (double)int y con mezclar int+double en las operaciones mat en general.

Esto da la sobrecarga más salvaje al procesador - sólo un comando de ensamblador tan caro. Si cuentas en doble, sigue contando en doble y no cambies a tipos enteros.

Comandos como cvtsi2sd/cvttsd2si son muy largos. Un pequeño consejo en el artículo"La instrucción x86 más lenta", villano número 2.

Gracias por un artículo tan valioso.


Pero para ser honesto, no entiendo por qué entonces en este simple 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 suma de long con conversión de tipo double a long es mucho más rápida que la suma de double del mismo array sin conversión

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 микросекунд
 

En primer lugar, hay que fijarse en el código ensamblador y en el resultado de las optimizaciones de casos extremadamente sencillos (hace tiempo que la supermicrosíntesis es engañosa). Es fácil encontrarse con un caso ideal de implantación de transportadores.

En segundo lugar, casi nadie puede garantizar cómo se compilará tal o cual código y cuánto tiempo tardará en ejecutarse.

Sólo hay que añadir una línea/comando más en el código y la velocidad cambia drásticamente. El código/datos reales bien podrían salir de la caché L1/L2 y eso es todo.

¿Cómo le ha funcionado? En teoría/superestética parece que los comandos enteros ayudarán en la velocidad, pero en el código real es una sangría. Porque hay decenas/centenares de veces más código, no hay convección, se salta constantemente de cálculos enteros a reales y la optimización es limitada.

 
Renat Fatkhullin:


¿Por qué la inicialización de arrays de cualquier tipo en MQL4 es más de 10 veces más lenta que en MQL5?

 
Реter Konow:

¿Por qué la inicialización de arrays de cualquier tipo en MQL4 es más de 10 veces más lenta que en MQL5?

Porque todas las matrices allí son dinámicas y el lenguaje es diez veces más lento.

 
Esa es una respuesta genial)).
Diez veces más lento porque diez veces más lento)).
 

Un indicador ultrarrápido de cientos de medias móviles, implementado en Canvas.

100 líneas MA (paso de periodo 10) - tiempo de cálculo y visualización en pantalla - 4-7 milisegundos


1000 líneas MA (periodo paso 1) - tiempo de cálculo y visualización - 20-30 milisegundos.


No he probado demasiado el código. Es posible que haya errores. Implementado sólo para barras de un píxel de grosor (se fuerza a esta escala). También la tasa de refresco de la pantalla no está optimizada. Todas las líneas se calculan y se emiten completamente en cada tic.

#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));
  }
//+------------------------------------------------------------------+
Archivos adjuntos:
MultiMA.mq5  9 kb
 
Nikolai Semko:

Un indicador ultrarrápido de cientos de medias móviles, implementado en Canvas.

100 líneas MA (paso de periodo 10) - tiempo de cálculo y visualización en pantalla - 4-7 milisegundos


1000 líneas MA (paso de periodo 1) - tiempo de cálculo y visualización - 20-30 milisegundos


Genial, con los indicadores estándar todo estaría muerto

 
Maxim Dmitrievsky:

genial, los indicadores estándar lo habrían colgado todo.

y luego habría una milla de código...

quizás incluso eso sólo se pueda hacer con una plantilla. No sé sobre la limitación del número de líneas del indicador en el cuerpo de un indicador.

 
Nikolai Semko:

...

No conozco la limitación del número de líneas del indicador en el cuerpo de un indicador.

Hay un límite. Se pueden hacer hasta 512 buffers de indicadores >>>https://www.mql5.com/ru/docs/indicators

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