mql5 언어의 특징, 미묘함 및 작업 방법 - 페이지 84

 
알랭 벌리앙 :

이를 입증하기 위해 벤치마크 코드를 제공할 수 있습니까?

 #define BENCH(A)                                                              \
{                                                                             \
   const ulong StartTime = GetMicrosecondCount ();                              \
  A;                                                                          \
   Print ( "Time[" + #A + "] = " + ( string )( GetMicrosecondCount () - StartTime)); \
}

double Bench1( const int Size, const string Str )
{
   double Tmp = 0 ;
  
   for ( int i = 0 ; i < Size; i++)
    Tmp += ( double )Str;

   return (Tmp);
}

double Bench2( const int Size, const string Str )
{
   double Tmp = 0 ;;
  
   for ( int i = 0 ; i < Size; i++)
    Tmp += StringToDouble (Str);

   return (Tmp);
}

double Bench3( const int Size, const string Str )
{
   double Tmp = 0 ;
  
   for ( int i = 0 ; i < Size; i++)
    Tmp += StringToDouble2(Str); // https://www.mql5.com/ru/forum/170952/page83#comment_7121066

   return (Tmp);
}

void OnStart ()
{  
   const string Str = "123.456" ;
  
  BENCH( Print (Bench1( 1 e7, Str)));
  BENCH( Print (Bench2( 1 e7, Str)));
  BENCH( Print (Bench3( 1 e7, Str)));
}


결과( 릴리스 )

 1234559999.924436
Time [ Print (Bench1( 1 e7,Str))] = 1656182
1234559999.924436
Time [ Print (Bench2( 1 e7,Str))] = 1639179
1234559999.924436
Time [ Print (Bench3( 1 e7,Str))] = 147382


추신 그리고 이것은 프로파일링 모드에서 실행하면 일어나는 일입니다.

 1234559999.924436
Time [ Print (Bench1( 1 e7,Str))] = 1757705
1234559999.924436
Time [ Print (Bench2( 1 e7,Str))] = 1877177
1234559999.924436
Time [ Print (Bench3( 1 e7,Str))] = 4578266

불행히도 이 경우 프로파일러를 신뢰할 수 없습니다.

 
fxsaber :


결과( 릴리스 )


추신 그리고 이것은 프로파일링 모드에서 실행하면 일어나는 일입니다.

뿐만 아니라 이 경우 프로파일러를 신뢰할 수 없습니다. Bench1도 릴리스 버전보다 10배 빠르게 실행됩니다!

덕분에.

결과 ( 릴리스 )

 Time [Bench1( 1 e7,Str)] = 1680754
Time [Bench2( 1 e7,Str)] = 1646789
Time [Bench3( 1 e7,Str)] = 143408     more then 10 times faster !!! 

전략 고문과 함께 테스트했습니다.

2018.04.16 14:24:28.049    Core 1    OnTester result 39725470 (µs bench1)
2018.04.16 14:26:14.629    Core 1    OnTester result 39270950 (µs bench2)
2018.04.16 14:27:13.566    Core 1    OnTester result 20467067 (µs bench3)

또 다른 2배 더 빠릅니다(그러나 10배 이하, 이는 확실히 컴파일러 최적화로 인한 것임).

파일:
170952.mq5  6 kb
 
알랭 벌리앙 :

전략 고문과 함께 테스트했습니다.

2018.04.16 14:24:28.049    Core 1    OnTester result 39725470 (µs bench1)
2018.04.16 14:26:14.629    Core 1    OnTester result 39270950 (µs bench2)
2018.04.16 14:27:13.566    Core 1    OnTester result 20467067 (µs bench3)

또 다른 2배 더 빠릅니다 (그러나 10배 이하, 이는 확실히 컴파일러 최적화로 인한 것임).

OnTick 계산뿐만 아니라 틱 생성 시간을 측정합니다.

다음은 OnTick 전용 동결입니다.

 #define PROFILER_OnTick // Замеряет чистое время выполнения всех OnTick - немного замедляет общую работу
#include <TesterBenchmark.mqh> // https://www.mql5.com/ru/code/18804

input int bench= 1 ; // between 1 and 3

void OnTick ()
{
   static const string Str = "123.456" ;

   switch (bench)
  {
     // https://www.mql5.com/ru/forum/170952/page84#comment_7121207
     case 1 : Bench1( 1 , Str); break ;
     case 2 : Bench2( 1 , Str); break ;
     case 3 : Bench3( 1 , Str); break ;
  }  
}


벤치1

i = 0 Pass = 0 OnTester = 3.729 s.: OnTick Profiler: Count = 7197033 , Interval = 1.895 s ., 3796990.9 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent- 127.0 . 0.1 - 3000 build = 1795
i = 1 Pass = 1 OnTester = 3.843 s.: OnTick Profiler: Count = 7197033 , Interval = 1.950 s., 3690523.1 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent- 127.0 . 0.1 - 3000 build = 1795


벤치3

i = 0 Pass = 0 OnTester = 2.280 s.: OnTick Profiler: Count = 7197033 , Interval = 0.631 s ., 11404799.6 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent- 127.0 . 0.1 - 3000 build = 1795
i = 1 Pass = 1 OnTester = 2.340 s.: OnTick Profiler: Count = 7197033 , Interval = 0.640 s., 11242184.6 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent- 127.0 . 0.1 - 3000 build = 1795


세 번. BenchX 함수의 다중 호출 이후 10배 가속도를 얻지 못합니다. StringToDouble2 자체는 실제로 10배 더 빠릅니다.

 
fxsaber :

OnTick 계산뿐만 아니라 틱 생성 시간을 측정합니다.

...

당신이 맞습니다.

10배 더 빠르다는 사실에 정말 놀랐지만 문자열에 유효한 이중 값이 포함되어 있다는 것을 알고 있는 경우에만 함수 를 사용할 수 있습니다.

2018.04.16 17:14:16.183 170952_180416(EURUSD, H1) StringToDouble2(abcdef)=5456784.0

 
알렉세이 비아즈미킨 :

감사합니다. 하지만 이 스크립트도 잘못 저장됩니다.

제 모니터에서는 오른쪽에 있는 제한이 세로선으로 표시되어 있는데, 화면이 이 선을 훨씬 넘어섰습니다.

서비스 데스크에서 인용하려면:

이 경우 ChartScreenShot 도움말은 문자 그대로 받아들여야 합니다.

align_mode=ALIGN_RIGHT

【인】 좁은 스크린샷 출력 모드. ENUM_ALIGN_MODE 열거의 값입니다. ALIGN_RIGHT는 오른쪽 정렬(끝에서 출력)을 의미합니다. ALIGN_LEFT는 왼쪽 정렬을 지정합니다.

즉, ALIGN_RIGHT 정렬이 지정되면 차트가 오른쪽 테두리로 강제 스크롤되며 이는 명령을 실행하는 것과 동일합니다.

ChartNavigate(0,CHART_END,0);

이 동작은 아직 ChartNavigate() 함수가 없었을 때 (역사적으로 그렇게) 수년 전에 설정되었습니다. align_mode=ALIGN_RIGHT를 설정하면 그래프의 오른쪽 가장자리가 정확히 캡처됩니다.

그리고 ChartNavigate() 함수가 추가되었을 때 ChartScreenShot 함수의 동작은 변경되지 않았습니다.

따라서 원하는 효과를 얻으려면(차트를 오른쪽 가장자리로 스크롤하지 않음) - align_mode 매개변수에 ALIGN_LEFT 값을 사용하십시오.

 
알랭 벌리앙 :

문자열에 유효한 이중 값이 포함되어 있다는 것을 알고 있는 경우에만 함수 를 사용할 수 있습니다.

2018.04.16 17:14:16.183 170952_180416(EURUSD, H1) StringToDouble2(abcdef)=5456784.0

수정됨, 이제 원본처럼 작동함

 #define PRINT(A) Print ( #A + " = " + ( string )(A))

void OnStart ()
{    
   const string Str[] = { "123.456" , "-asdf1234" , "12as" , ".34 a" , "..23" , "1.." };

   for ( int i = 0 ; i < ArraySize (Str); i++)
  {
    PRINT(Str[i]);
    
    PRINT(( double )Str[i]);
    PRINT(StringToDouble2(Str[i])); // https://www.mql5.com/ru/forum/170952/page83#comment_7121066
    
     Print ( "" );
  }
}
 

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

mql5 언어의 특징, 미묘함 및 작업 방법

fxsaber , 2018.04.16 13:23

 double StringToDouble2( const string Str, const uint StartPos = 0 )

할당된 const를 제거하면 함수의 실행 시간이 두 배가 됩니다. 이것은 컴파일러가 항상 최적의 코드를 생성하는 것은 아니며 이러한 종류의 힌트가 필요함을 나타냅니다.

 
fxsaber :

할당된 const를 제거하면 함수의 실행 시간이 두 배가 됩니다. 이것은 컴파일러가 항상 최적의 코드를 생성하는 것은 아니며 이러한 종류의 힌트가 필요함을 나타냅니다.

흥미롭네요. 감사합니다.

이미 답변이 있는 경우 코드를 편집하지 마십시오. 업데이트했다는 알림을 받지 못했습니다.

 
fxsaber :

할당된 const를 제거하면 함수의 실행 시간이 두 배가 됩니다. 이것은 컴파일러가 항상 최적의 코드를 생성하는 것은 아니며 이러한 종류의 힌트가 필요함을 나타냅니다.

매우 흥미로운...
왜 이런 일이 일어나는지 생각이 있으십니까?

메커니즘은 무엇입니까?

 

특정 기간 동안 전체 막대를 포함하는 MQL5를 사용하여 화면에서 가져온 스크린샷의 너비를 결정하기 위해 다음과 같은 솔루션을 제안합니다.

특이성은 차트의 다른 근사값에서 스크린샷의 너비를 수정해야 한다는 사실로 밝혀졌습니다.

실제 "계수"는 저울이 있거나 없는 옵션에 대해 (특히 저에게) 다른 것으로 나타났습니다.

 if (Use_Shakala== false )
 
 {
   ChartSetInteger ( 0 , CHART_SHOW_PRICE_SCALE , 0 ); //Показывать или нет ценовую шкалу
   int TotalPixel=( int ) ChartGetInteger ( 0 , CHART_WIDTH_IN_PIXELS );   // Ширина графика в пикселях
   int WidthBar= int ( 1 << ChartGetInteger ( 0 , CHART_SCALE ));             // сколько пикселей между барами
   int FirstBar=( int ) ChartGetInteger ( 0 , CHART_FIRST_VISIBLE_BAR );   // номер первого (левого) бара на экране
   int VisibleBars=( int ) ChartGetInteger ( 0 , CHART_VISIBLE_BARS );     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(- 1 );               // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(- 1 ):((FirstBar-BarNr)*WidthBar);   // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar< 0 )?(- 1 ):LeftPixelOfBar+WidthBar- 1 ;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel- 1 ;   // проверяем не за пределами ли экрана 

       if (Zoom== 0 )ZoomX= 6 ;
       if (Zoom== 1 )ZoomX= 5 ;
       if (Zoom== 2 )ZoomX= 5 ;
       if (Zoom== 3 )ZoomX= 4 ;
       if (Zoom== 4 )ZoomX= 2 ;
       if (Zoom== 5 )ZoomX= 0 ;

  pp=WidthBar*((Shift_Start-Shift_Stop)*(- 1 )+ 2 )+ZoomX;
}

   if (Use_Shakala== true )
  {
   ChartSetInteger ( 0 , CHART_SHOW_PRICE_SCALE , 1 ); //Показывать или нет ценовую шкалу
   int TotalPixel=( int ) ChartGetInteger ( 0 , CHART_WIDTH_IN_PIXELS );   // Ширина графика в пикселях
   int WidthBar= int ( 1 << ChartGetInteger ( 0 , CHART_SCALE ));             // сколько пикселей между барами
   int FirstBar=( int ) ChartGetInteger ( 0 , CHART_FIRST_VISIBLE_BAR );   // номер первого (левого) бара на экране
   int VisibleBars=( int ) ChartGetInteger ( 0 , CHART_WIDTH_IN_BARS );     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(- 1 );               // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(- 1 ):((FirstBar-BarNr)*WidthBar);   // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar< 0 )?(- 1 ):LeftPixelOfBar+WidthBar- 1 ;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel- 1 ;   // проверяем не за пределами ли экрана 

       if (Zoom== 0 )ZoomX= 1 ;
       if (Zoom== 1 )ZoomX= 1 ;
       if (Zoom== 2 )ZoomX= 1 ;
       if (Zoom== 3 )ZoomX= 3 ;
       if (Zoom== 4 )ZoomX= 2 ;
       if (Zoom== 5 )ZoomX= 0 ;    
  pp=WidthBar*((Shift_Start-Shift_Stop)*(- 1 )+ 2 - 0.5 )+ZoomX+Schkala;
  
  }
//pp 		 - ширина скриншота
//Shift_Start    - номер левого бара, который целиком должен попасть на скрин
//Shift_Stop     - номер правого бара, который целиком должен попасть на скрин
//Schkala        - ширина цифровой шкалы по методу fxsaber
//Zoom           - степень приближение экрана
사유: