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

 

이것이 내가 생각해 낸 것입니다.

 int log2_( ulong n)
{
   if (n== 0 ) return - 1 ;

   #define M(n, i, base, S) ( n >= ( ulong ( 1 )<<(i)) ? S(n, i+base/ 2 ) : S(n, i-(base+ 1 )/ 2 ) )

   #define S_0(n, i)  i
   #define S_1(n, i)  M(n, i, 1 , S_0)
   #define S_2(n, i)  M(n, i, 2 , S_1)
   #define S_4(n, i)  M(n, i, 4 , S_2)
   #define S_8(n, i)  M(n, i, 8 , S_4)
   #define S_16(n, i) M(n, i, 16 , S_8)
   #define S(n)       M(n, 32 , 32 , S_16)

   return S(n); 
}

이론적으로 이것은 가능한 모든 것 중 가장 빠릅니다. 모든 계산은 상수로 이루어지므로 컴파일 중에 계산됩니다. 총 6번의 연속적인 비교만 가능하며 그 이상은 아닙니다. 그러나 이 옵션은 이전 옵션보다 느리게 작동합니다. 이유가 무엇인지 이해할 수 없습니다.

 
Alexey Navoykov :

이것이 내가 생각해 낸 것입니다.

이론적으로 이것은 가능한 모든 것 중 가장 빠릅니다. 모든 계산은 상수로 이루어지므로 컴파일 중에 계산됩니다. 총 6번의 연속적인 비교만 가능하며 그 이상은 아닙니다. 그러나 이 옵션은 이전 옵션보다 느리게 작동합니다. 이유가 무엇인지 이해할 수 없습니다.

2로 나누면 속도가 느려지나요? shift 로 바꾸시겠습니까? 계산된 상수가 즉시 계산되어야 한다는 의심(이 경우 - 정의의 이동도 상수로 대체되어야 함).

추가로 - "질문" - 제가 아는 바와 같이 이것은 다소 논란의 여지가 있는 연산자입니다. 한 번, 20년 전에 C ++에서 확인했습니다. 때때로 "질문"은 일반 if 문보다 더 긴 코드를 생성합니다. 여기도 마찬가지 아닐까요?

그리고 반환 코드를 uint로 만들었습니다. 서명된 값과 서명되지 않은 값을 변환할 때 몇 가지 검사가 진행 중인 경우 어떻게 됩니까?

스스로 실험 할 방법은 없지만 프로세서가 안구에로드됩니다 ... 텍스트조차도 "슬립으로"입력됩니다 ...

 
Georgiy Merts :

2로 나누면 속도가 느려지나요? shift 로 바꾸시겠습니까? 계산된 상수가 즉시 계산되어야 한다는 의심(이 경우 - 정의의 이동도 상수로 대체되어야 함).

또한 - "질문 질문" - 내가 아는 바와 같이 이것은 다소 논란의 여지가 있는 연산자입니다 ...

부서를 교대로 바꿔도 효과가 없습니다. 결과 표현식이 너무 길어서 컴파일러가 끝까지 최적화하지 않은 것 같습니다.

그러나 Optimize=0으로 테스트를 수행했습니다. 그리고 최적화가 활성화되었을 때 모든 것이 제자리에 놓였습니다. 두 번째 옵션은 약 1.5배 더 빠릅니다. 빙고!

최적화가 비활성화된 경우 두 번째 옵션은 작은 값의 경우 약간 느리지만 큰 값의 경우 약간 더 빠릅니다. 요컨대, 두 번째 옵션이 확실히 더 좋습니다.

 
Alexey Navoykov :

이것이 내가 생각해 낸 것입니다.

이론적으로 이것은 가능한 모든 것 중 가장 빠릅니다. 모든 계산은 상수로 이루어지므로 컴파일 중에 계산됩니다. 총 6번의 연속적인 비교만 가능하며 그 이상은 아닙니다. 그러나 이 옵션은 이전 옵션보다 느리게 작동합니다. 이유가 무엇인지 이해할 수 없습니다.

맞습니다. 귀하의 옵션이 가장 빠릅니다.

그냥 빈 테스트입니다. 성능을 테스트할 때 매우 자주 한 가지 중요한 점을 잊습니다. 계산된 값이 어디에도 사용되지 않으면 컴파일러는 단순히 계산을 수행하지 않습니다.

결국 이것은 논리적입니다. 요점이 무엇입니까? 그것은 양자 중첩과 같습니다. 아무도 보고 있지 않다면 달이 존재해야 하는 이유. "달은 쥐가 보고 있기 때문에 존재하는 것인가?" (알버트 아인슈타인). :))

따라서 체크섬을 계산하고 인쇄하는 이 버전의 테스트가 더 정확합니다.

 #property strict
#define   test(M,S,EX)        { long sum= 0 ; uint nn=( uint ) pow ( 10 ,M); ulong mss= GetMicrosecondCount (); for ( uint t12= 1 ;t12<=nn;t12++){EX;sum+=( long )n1;} \
                                 Print (S+ ": loops=" +( string )nn+ " μs=" + string ( GetMicrosecondCount ()-mss)+ " Контрольная сумма=" + string (sum));}

int log2( ulong n){
   if (n== 0 ) return - 1 ;
   #define S(k) if (n >= ( ulong ( 1 )<<k)) { i += k;  n >>= k; }
   int i= 0 ;  S( 32 );  S( 16 );  S( 8 );  S( 4 );  S( 2 );  S( 1 );   return i;
   #undef S}


static const uint ulLogTable[ 64 ] = {
0 , 58 , 1 , 59 , 47 , 53 , 2 , 60 , 39 , 48 , 27 , 54 , 33 , 42 , 3 , 61 ,
51 , 37 , 40 , 49 , 18 , 28 , 20 , 55 , 30 , 34 , 11 , 43 , 14 , 22 , 4 , 62 ,
57 , 46 , 52 , 38 , 26 , 32 , 41 , 50 , 36 , 17 , 19 , 29 , 10 , 13 , 21 , 56 ,
45 , 25 , 31 , 35 , 16 , 9 , 12 , 44 , 24 , 15 , 8 , 23 , 7 , 6 , 5 , 63 };

uint _FastLog2( ulong ulInput){
   ulInput |= ulInput >> 1 ;
   ulInput |= ulInput >> 2 ;
   ulInput |= ulInput >> 4 ;
   ulInput |= ulInput >> 8 ;
   ulInput |= ulInput >> 16 ;
   ulInput |= ulInput >> 32 ;  
   return (ulLogTable[( uint )((ulInput * 0x03f6eaf2cd271461 ) >> 58 )]);};
   
int log2_( ulong n)
{
   if (n== 0 ) return - 1 ;

   #define M(n, i, base, S) ( n >= ( ulong ( 1 )<<(i)) ? S(n, i+base/ 2 ) : S(n, i-(base+ 1 )/ 2 ) )

   #define S_0(n, i)  i
   #define S_1(n, i)  M(n, i, 1 , S_0)
   #define S_2(n, i)  M(n, i, 2 , S_1)
   #define S_4(n, i)  M(n, i, 4 , S_2)
   #define S_8(n, i)  M(n, i, 8 , S_4)
   #define S_16(n, i) M(n, i, 16 , S_8)
   #define S(n)       M(n, 32 , 32 , S_16)

   return S(n); 
}

void OnStart (){
   srand ( GetTickCount ());
   ulong n1;
  test( 8 , "MathLog" ,n1= ulong ( MathLog (( double )t12)/ MathLog ( 2.0 )))
  test( 8 , "log2" ,n1=log2(t12))
  test( 8 , "log2_" ,n1=log2_(t12))
  test( 8 , "_FastLog2" ,n1=_FastLog2(t12))}

결과:

 2019.01 . 05 02 : 30 : 03.681 TestLog (.BrentCrud,H4) MathLog :   loops= 100000000 μs= 805196 Контрольная сумма= 2465782300
2019.01 . 05 02 : 30 : 04.092 TestLog (.BrentCrud,H4) log2:      loops= 100000000 μs= 410657 Контрольная сумма= 2465782300
2019.01 . 05 02 : 30 : 04.234 TestLog (.BrentCrud,H4) log2_:     loops= 100000000 μs= 141975 Контрольная сумма= 2465782300
2019.01 . 05 02 : 30 : 04.432 TestLog (.BrentCrud,H4) _FastLog2: loops= 100000000 μs= 198015 Контрольная сумма= 2465782300
그리고 두 번째 장소는 여전히 log2가 아닌 _FastLog2입니다. :))
 
Nikolai Semko :

그냥 빈 테스트입니다. 성능을 테스트할 때 매우 자주 한 가지 중요한 점을 잊습니다. 계산된 값이 어디에도 사용되지 않으면 컴파일러는 단순히 계산을 수행하지 않습니다.

결국 이것은 논리적입니다. 요점이 무엇입니까? 그것은 양자 중첩과 같습니다. 아무도 보고 있지 않다면 달이 존재해야 하는 이유. "달은 쥐가 보고 있기 때문에 존재하는 것인가?" (알버트 아인슈타인). :))

따라서 체크섬을 계산하고 인쇄하는 이 버전의 테스트가 더 정확합니다.

코드가 혼란스럽습니다. 정의에 사용된 변수는 프로그램 코드의 다른 끝에 위치하므로 이러한 혼란을 이해하는 것이 불편합니다. 그러나 요점은 이것에 있는 것이 아니라 테스트 결과를 신뢰할 수 있는 것으로 간주할 수 없다는 사실입니다. 컴파일러는 함수에 전달된 값의 알고리즘을 미리 알고 있습니다. 따라서 테스트를 최적화합니다. 난수를 계산해야 합니다.

그건 그렇고, 왜 코드에 srand가 있습니까? 처음에는 랜덤으로 사용하시는 줄 알았는데, 사실은 - 아닙니다.

내 코드는 다음과 같습니다.

 void OnStart ()
{
   Print ( "OnStart" );
   srand ( GetTickCount ());
   int count= 50000000 ;
   
   #define TEST(func) { \ 
     ulong sum= 0 ; \
     ulong mcscount= GetMicrosecondCount (); \
     for ( int i= 0 ; i<count; i++) \
      sum += func( rand () | rand ()<< 15 ); \
     Print ( "Result " + #func + ":  sum=" ,sum, "  time=" ,( GetMicrosecondCount ()-mcscount)/ 1000 , " ms" ); \    
  }
  
  TEST(log2);
  TEST(log2_);
}
 
Alexey Navoykov :

코드가 혼란스럽습니다. 정의에 사용된 변수는 프로그램 코드의 다른 끝에 위치하므로 이러한 혼란을 이해하는 것이 불편합니다. 그러나 요점은 이것에 있는 것이 아니라 테스트 결과를 신뢰할 수 있는 것으로 간주할 수 없다는 사실입니다. 컴파일러는 함수에 전달된 값의 알고리즘을 미리 알고 있습니다. 따라서 테스트를 최적화합니다. 난수를 계산해야 합니다.

그건 그렇고, 왜 코드에 srand가 있습니까? 처음에는 랜덤으로 사용하시는 줄 알았는데, 사실은 - 아닙니다.

내 코드는 다음과 같습니다.

코드는 내 것이 아닙니다. 방금 수정하고 체크섬의 정체를 확인하고 루프에서 상대적으로 비싼 rand 함수를 제거하기 위해 rand를 버렸고 srand는 단순히 버리는 것을 잊었습니다.

나는 랜드를 반환합니다. 맞습니다. 컴파일러는 연속 값의 로그 합계 루프를 최적화합니다. 나는 놀랐지만. 나는 그가 그것을하는 방법을 이해하지 못합니다. 아마도 우리가 고려하지 않은 것이 있을 것입니다.

 #property strict
#define   test(M,S,EX)        { srand ( 45 ); long sum= 0 ; uint nn=( uint ) pow ( 10 ,M); ulong mss= GetMicrosecondCount (); for ( uint t12= 1 ;t12<=nn;t12++){EX;sum+=( long )n1;} \
                                 Print (S+ ": loops=" +( string )nn+ " μs=" + string ( GetMicrosecondCount ()-mss)+ " Контрольная сумма=" + string (sum));}

int log2( ulong n){
   if (n== 0 ) return - 1 ;
   #define S(k) if (n >= ( ulong ( 1 )<<k)) { i += k;  n >>= k; }
   int i= 0 ;  S( 32 );  S( 16 );  S( 8 );  S( 4 );  S( 2 );  S( 1 );   return i;
   #undef S}


static const uint ulLogTable[ 64 ] = {
0 , 58 , 1 , 59 , 47 , 53 , 2 , 60 , 39 , 48 , 27 , 54 , 33 , 42 , 3 , 61 ,
51 , 37 , 40 , 49 , 18 , 28 , 20 , 55 , 30 , 34 , 11 , 43 , 14 , 22 , 4 , 62 ,
57 , 46 , 52 , 38 , 26 , 32 , 41 , 50 , 36 , 17 , 19 , 29 , 10 , 13 , 21 , 56 ,
45 , 25 , 31 , 35 , 16 , 9 , 12 , 44 , 24 , 15 , 8 , 23 , 7 , 6 , 5 , 63 };

uint _FastLog2( ulong ulInput){
   ulInput |= ulInput >> 1 ;
   ulInput |= ulInput >> 2 ;
   ulInput |= ulInput >> 4 ;
   ulInput |= ulInput >> 8 ;
   ulInput |= ulInput >> 16 ;
   ulInput |= ulInput >> 32 ;  
   return (ulLogTable[( uint )((ulInput * 0x03f6eaf2cd271461 ) >> 58 )]);};
   
int log2_( ulong n)
{
   if (n== 0 ) return - 1 ;

   #define M(n, i, base, S) ( n >= ( ulong ( 1 )<<(i)) ? S(n, i+base/ 2 ) : S(n, i-(base+ 1 )/ 2 ) )

   #define S_0(n, i)  i
   #define S_1(n, i)  M(n, i, 1 , S_0)
   #define S_2(n, i)  M(n, i, 2 , S_1)
   #define S_4(n, i)  M(n, i, 4 , S_2)
   #define S_8(n, i)  M(n, i, 8 , S_4)
   #define S_16(n, i) M(n, i, 16 , S_8)
   #define S(n)       M(n, 32 , 32 , S_16)

   return S(n); 
}

void OnStart (){
   ulong n1,n;
  test( 8 , "MathLog" ,n=( rand ()+ 1 )*( rand ()+ 1 );n1= ulong ( MathLog (( double )n)/ MathLog ( 2.0 )))
  test( 8 , "log2" ,n=( rand ()+ 1 )*( rand ()+ 1 );n1=log2(n))
  test( 8 , "log2_" ,n=( rand ()+ 1 )*( rand ()+ 1 );n1=log2_(n))
  test( 8 , "_FastLog2" ,n=( rand ()+ 1 )*( rand ()+ 1 );n1=_FastLog2(n))}

결과:

 2019.01 . 05 04 : 10 : 25.808 TestLog (EURUSD,H1)     MathLog :   loops= 100000000 μs= 1168737 Контрольная сумма= 2661391201
2019.01 . 05 04 : 10 : 26.474 TestLog (EURUSD,H1)     log2:      loops= 100000000 μs= 665631   Контрольная сумма= 2661391201
2019.01 . 05 04 : 10 : 27.315 TestLog (EURUSD,H1)     log2_:     loops= 100000000 μs= 841299   Контрольная сумма= 2661391201
2019.01 . 05 04 : 10 : 27.694 TestLog (EURUSD,H1)     _FastLog2 :  loops= 100000000 μs= 378627    Контрольная сумма= 2661391201
   

현재 승자는 _FastLog2입니다.

 
Nikolai Semko :

결과:

현재 승자는 _FastLog2입니다.

값이 무작위인 경우 어떻게 모든 곳에서 동일한 체크섬을 얻었는지 궁금합니다.

 
Alexey Navoykov :

값이 무작위인 경우 어떻게 모든 곳에서 동일한 체크섬을 얻었는지 궁금합니다.

모든 기능에 대한 srand(45)

나도 처음에는 그렇게 했지만 다른 체크섬이 생겼습니다. tk. rand()*rand()가 0이 될 수 있다는 점을 고려하지 않았으며 이는 체크섬을 깨뜨립니다. 이제 0에서 벗어나기 위해 하나가 추가되었습니다.

 
Nikolai Semko :

모든 기능에 대한 srand(45)

나도 처음에는 그렇게 했지만 다른 체크섬이 생겼습니다. tk. rand()*rand()가 0이 될 수 있다는 점을 고려하지 않았으며 이는 체크섬을 깨뜨립니다. 이제 0에서 벗어나기 위해 하나가 추가되었습니다.

속도 측정에 대해 구체적으로 이야기하는 경우 동일한 체크섬이 필요한 이유는 무엇입니까? 이 경우 합계의 본질은 컴파일러가 코드를 잘라내지 못하도록 방지하는 것뿐입니다. 그리고 srand(45)를 수행하여 테스트를 다시 최적화할 수 있습니다.

그건 그렇고, 약 0. FastLog2에는 제로 검사가 없으므로 우선적으로 시작할 수 있습니다. 그러나 올바르게 테스트된 경우 여전히 log2보다 1.5~2배 느립니다)

 
Alexey Navoykov :
속도 측정에 대해 구체적으로 이야기하는 경우 동일한 체크섬이 필요한 이유는 무엇입니까? 이 경우 합계의 본질은 컴파일러가 코드를 잘라내지 못하도록 방지하는 것뿐입니다. 그리고 srand(45)를 수행하여 테스트를 다시 최적화할 수 있습니다.

여기에서 컴파일러의 기능을 과대평가합니다. srand(45) 제거 - 체크섬은 다르지만 속도 결과는 유지됩니다.

또한, 실험의 순도에 대해 계산이 동일하다는 사실에 의해 안내되었습니다. 모든 기능에 대한 자세한 내용은 다루지 않았습니다. 때로는 함수 매개변수의 값이 실행 시간에 영향을 미칠 수 있습니다.

특히 동시에 알고리즘의 정확성을 확인합니다.