A lona é legal! - página 19

 
Renat Fatkhullin:

Acontece que eu estava olhando para a freqüência de geração da web, não para a freqüência de saída.

Estes são números diferentes, múltiplos uns dos outros.

Acontece que eu estava calculando a freqüência de geração da web (sem saída) e a freqüência de saída (sem geração) um pouco errada

Aqui está uma versão mais correta.


Resultados sobre meu processador:

Se você tomar o tempo simplesmente gerando um quadro de 200 círculos alisados sem saída, isso acontece a cerca de 500 quadros por segundo.

formando uma moldura de 200 círculos não molhados sem saída - cerca de 1000 fps.

A freqüência da saída da imagem (tela) em si (função de atualização) é de cerca de 650 fps.

Você realmente trabalhou muito!

Arquivos anexados:
 
Renat Fatkhullin:

Cuidado com as conversões em massa dos tipos (int)double ou (double)int e a mistura int+double em operações de esteiras em geral.

Isto dá a mais selvagem sobrecarga ao processador - apenas um comando de montagem tão caro. Se você contar em dobro, continue contando em dobro e não mude para os tipos inteiros.

Comandos como cvtsi2sd/cvttsd2si são muito longos. Uma pequena dica no artigo"A instrução x86 mais lenta", vilão número 2.

Obrigado por um artigo muito valioso.


Mas, para ser honesto, não entendo por que então, neste simples roteiro:

#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)+" микросекунд");   
  }

a soma de longo com conversão do tipo duplo em longo é muito mais rápida do que a soma do duplo da mesma matriz sem conversão

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

Em primeiro lugar, deve-se observar o código de montagem e o resultado de otimizações de casos extremamente simples (os supermicrossintéticos têm sido enganosos há muito tempo). É fácil encontrar um caso ideal de implementação de esteiras transportadoras.

Em segundo lugar, quase ninguém pode garantir como este ou aquele código será compilado e quanto tempo levará para ser executado.

Basta adicionar mais uma linha/comando no código e a velocidade muda drasticamente. O código/dados reais podem muito bem sair do cache L1/L2 e pronto.

Como funcionou para você? Em teoria/super-sintéticos parece que os comandos inteiros ajudarão na velocidade, mas em código real é um dreno. Como há dezenas/centenas de vezes mais código, não há convectorização, saltar constantemente do inteiro para cálculos reais e a otimização é limitada.

 
Renat Fatkhullin:


Por que a inicialização de matrizes de qualquer tipo na MQL4 é mais de 10 vezes mais lenta do que na MQL5?

 
Реter Konow:

Por que a inicialização de matrizes de qualquer tipo na MQL4 é mais de 10 vezes mais lenta do que na MQL5?

Porque todas as matrizes lá são dinâmicas e a linguagem é dez vezes mais lenta.

 
Essa é uma resposta legal)).
Dez vezes mais lento porque dez vezes mais lento)).
 

Um indicador ultra-rápido de centenas de médias móveis, implementado em Tela.

100 linhas MA (período etapa 10) - tempo de cálculo e exibição na tela - 4-7 milissegundos


1000 linhas MA (período etapa 1) - tempo de cálculo e exibição - 20-30 milissegundos.


Eu não testei muito o código. Pode haver insetos. Implementado apenas para uma barra de espessura de um pixel (é forçado a esta escala). Também a taxa de atualização da tela não é otimizada. Todas as linhas são calculadas e a saída completa a cada 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));
  }
//+------------------------------------------------------------------+
Arquivos anexados:
MultiMA.mq5  9 kb
 
Nikolai Semko:

Um indicador ultra-rápido de centenas de médias móveis, implementado em Tela.

100 linhas MA (período etapa 10) - tempo de cálculo e exibição na tela - 4-7 milissegundos


1000 linhas MA (período etapa 1) - tempo para cálculo e exibição - 20-30 milissegundos


frio, com indicadores padrão tudo estaria morto

 
Maxim Dmitrievsky:

frio, os indicadores padrão teriam pendurado tudo.

e depois haveria uma milha de código...

talvez até mesmo isso só possa ser feito com um modelo. Não sei quanto à limitação do número de linhas indicadoras no corpo de um indicador.

 
Nikolai Semko:

...

Não ciente da limitação do número de linhas indicadoras no corpo de um indicador.

Há um limite. Podem ser feitos até 512 buffers indicadores >>>https://www.mql5.com/ru/docs/indicators

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