캔버스 멋지다! - 페이지 19

 
Renat Fatkhullin :

출력 주파수가 아닌 캔버스 생성 주파수를 보고 있는 것으로 나타났습니다.

이들은 서로의 배수인 서로 다른 숫자입니다.

캔버스 생성 빈도(출력 없음)와 출력 빈도(생성 없음)를 약간 잘못 계산한 것으로 나타났습니다.

여기에 더 정확한 버전이 있습니다.


내 프로세서에 대한 결과:

출력 없이 200개의 부드러운 원에서 프레임을 형성하는 데만 시간을 들이면 이는 초당 약 500프레임의 빈도로 발생합니다.

출력이 없는 200개의 매끄럽지 않은 원의 프레이밍 - 초당 약 1000프레임.

화면에 이미지(캔버스)를 표시하는 기능 자체의 빈도(업데이트 기능)는 초당 약 650프레임입니다.

정말 수고하셨습니다!

파일:
 
Renat Fatkhullin :

(int)double 또는 (double)int와 같은 대량 변환의 화재처럼 조심하고 일반적으로 매트 연산에서 int+double을 혼합합니다.

이것은 프로세서에서 가장 큰 오버헤드를 제공합니다. 바로 값비싼 어셈블러 명령입니다. 이중으로 세는 경우 계속 계산하고 정수 유형으로 전환하지 마십시오.

cvtsi2sd/cvttsd2si와 같은 명령은 매우 깁니다. 기사 " 가장 느린 x86 명령 ", 악당 번호 2의 작은 팁.

매우 귀중한 기사에 감사드립니다.


하지만 솔직히 말해서 이 간단한 스크립트에서 왜 그런 것인지 이해가 되지 않습니다.

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

double 형식을 long으로 변환한 long의 합은 변환이 없는 동일한 배열의 double 합보다 눈에 띄게 빠릅니다.

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

먼저 어셈블리 코드와 매우 간단한 경우 의 최적화 결과 를 살펴봐야 합니다(초미세 합성은 오랫동안 오해의 소지가 있었습니다). 컨베이어 구현을 실행하는 것은 쉬운 일이며 이상적인 경우입니다.

둘째, 컴파일 방법과 이 코드 또는 저 코드를 실행하는 데 걸리는 시간을 보장할 수 있는 사람은 거의 없습니다.

코드에 추가 줄/명령어를 추가하는 것으로 충분하며 속도가 크게 변경됩니다. 실제 코드/데이터는 L1/L2 캐시에서 나올 수 있습니다.

어떻게 해결되었나요? 이론/초합성에 따르면 정수 명령이 속도에 도움이 되는 것처럼 보이지만 실제 코드에서는 소모됩니다. 수십/백 배 더 많은 코드가 있기 때문에 파이프라이닝이 없고 정수에서 실수로 계산의 지속적인 점프 및 최적화가 제한됩니다.

 
Renat Fatkhullin :


MQL4에서 모든 유형 의 어레이 초기화가 MQL5에서보다 10배 이상 느린 이유는 무엇입니까?

 
Реter Konow :

MQL4에서 모든 유형 의 어레이 초기화가 MQL5에서보다 10배 이상 느린 이유는 무엇입니까?

모든 배열이 동적이고 언어가 10배 느리기 때문입니다.

 
멋진 답변입니다.)
10배 느리기 때문에 10배 느려짐))).
 

Canvas에서 구현된 수백 이동 평균의 초고속 표시기.

100 MA 라인(기간 단계 10) - 계산 및 표시 시간 - 4-7밀리초


1000 MA 라인(기간 단계 1) - 계산 및 표시 시간 - 20-30밀리초


코드는 많이 테스트되지 않았습니다. 버그가 있을 수 있습니다. 두께가 1픽셀인 막대에 대해서만 구현됩니다(이러한 축척으로 강제 변환됨). 또한 화면 새로 고침 빈도가 최적화되지 않았습니다. 모든 라인이 계산되어 각 눈금에 완전히 표시됩니다.

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

Canvas에서 구현된 수백 이동 평균의 초고속 표시기.

100 MA 라인(기간 단계 10) - 계산 및 표시 시간 - 4-7밀리초


1000 MA 라인(기간 단계 1) - 계산 및 표시 시간 - 20-30밀리초


쿨, 표준 표시기를 통해 모든 것이 단단히 고정됩니다.

 
Maxim Dmitrievsky :

쿨, 표준 표시기를 통해 모든 것이 단단히 고정됩니다.

1킬로미터의 코드가 있을 것입니다 ...

아마도 이것은 템플릿으로만 수행할 수 있습니다. 한 지표의 본문에 있는 지표 행 수에 대한 제한을 인식하지 못합니다.

 
Nikolai Semko :

...

한 지표의 본문에 있는 지표 행 수에 대한 제한을 인식하지 못합니다.

제한이 있습니다. 최대 512개의 표시기 버퍼를 만들 수 있습니다. >>> https://www.mql5.com/ru/docs/indicators

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