오류, 버그, 질문 - 페이지 2160

 
Andrey Khatimlianskii :

MQ의 관점에서 보면 분명히 정확합니다. 항상 그렇듯이 우리는 더 편리하기 때문에 우리를 위해 결정했습니다.

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

프로필 메시지가 사라졌습니다.

레나트 팻쿨린 , 2018.03.08 10:31

호환성 모드에서 작동하는 기능의 양을 줄이기 위해 일시적으로 제거되었습니다.

전송 프로세스가 완료되는 즉시 새로운 기능을 추가할 것입니다.

이것은 새로운 초대형 다기능 시스템입니다.


새로운 채팅이 도입되고 있습니다.

 
Andrey Khatimlianskii :

MQ의 관점에서 보면 분명히 정확합니다. 항상 그렇듯이 우리는 더 편리하기 때문에 우리를 위해 결정했습니다.

텔레파시 수준으로 넘어 갑시다 ...))))))

 

주요 표시기의 이해할 수 없는 버그. H 1 미만의 시간 프레임에서만 발생 하며 터미널이 실행 되는 순간에만 발생합니다. 텍스트 오류 "S-v5(EURUSD,M10) 배열이 'S-v5.mq5'(211.54)의 범위를 벗어났습니다." 모든 버퍼에 대해 시계열 플래그가 설정되어 있어도 렌더링은 올바르게 수행되지만 역순으로 발생합니다.

템플릿의 구성은 기본 표시기(1번)(오류가 발생함), 추가 표시기(2번)(기본 표시기의 여러 핸들을 서로 다른 매개변수(보기 기간)와 결합), 표시기( 3) 지표 1)의 신호를 기반으로 메인 차트에 화살표를 표시하는 지표 2), 지표 2)의 신호를 기반으로 메인 차트에 화살표를 표시하는 지표 (4).

시간 프레임을 전환하고 템플릿을 다시 적용하면 2에서 4로 또는 1 아래에서만 2개의 지표를 제거하고 Market Watch에서 새 기호를 표시하고 이 템플릿을 적용하면 오류가 재현되지 않고 모든 지표가 올바르게 그려집니다. .  

 

컴파일 중 오류

 #import  "Test1.ex5"
       void f1();
#import  "Test2.dll"
       void f2();
#import
typedef void (*fn)();
void OnStart ()
{
    fn fn1 =        f1; //нормально
    fn fn2 =        f2; //Error: 'f2' - pointer to this function type is not supported yet
    fn fn3 = Test2::f2; //нормально
}
 

오류 메시지는 광범위한 코드에서 이유를 명확하게 나타내지 않습니다.

 struct A {
     void f( int     ) {}
     void g( int fn ) { f( fn ); } //Error: ')' - unexpected token ???
};
typedef void (*fn)();

아래는 분명하다

 struct A {
    void f( int     ) {}
    void g( int fn ) { f( fn ); } //Error: 'fn' - identifier already used
};
struct fn {};
 

오류 메시지 없음

 typedef void (*fn)();
void f( int i ) { Print ( __FUNCTION__ , ":" , i ); }
void OnStart ()
{
    f( fn() );
}

또한 실행되고 결과도 (!)

이 변형에서:

 typedef int (*fn)();
void OnStart () { Print ( fn() ); }

오류 라인으로의 전환이 작동하지 않습니다(Enter로)


 

컴파일 중 오류

    void g(   int ) {}
    void g( uint ) {}
#import "Test.ex5"
     void f(   int );
     void f( uint );
#import
typedef void (*fn1)(   int );
typedef void (*fn2)( uint );
void OnStart ()
{
    fn1 g1 = g; /*нормально и результат*/ g1( 1 ); //совпадает с ожидаемым
    fn2 g2 = g; /*нормально и результат*/ g2( 1 ); //совпадает с ожидаемым
    fn1 f1 = f; //Error: 'f' - cannot resolve function address
    fn2 f2 = f; /*нормально и результат*/ f2( 1 ); //совпадает с ожидаемым
                                                   //при наличии Test.ex5
}
 

작업 속도를 높이기 위해 이 예제 를 만들 때 우연히 하나의 기이한 상황에 부딪쳤습니다.

그리고 이제 이 이상함을 처리하려고 했을 때 나는 더욱 혼란스러워졌다.

따라서 계산에서 sqrt() 제곱근 함수를 사용합니다. 이 함수는 이중 배열을 만들어 우회하기로 결정했습니다.

왜냐하면 나는 항상 정수의 제곱근을 취한 다음 배열을 생성하는 것은 다음과 같습니다.

   double SQRT[];
   int ss=Width*Width+Height*Height;
   ArrayResize (SQRT,ss);
   for ( double w= 0 ;w<ss;w++) SQRT[( int )w]= sqrt (w);

SQRT[x] 배열에서 읽는 것이 sqrt(x) 함수보다 빠르다고 가정하는 것이 논리적입니다.
그리고 이것은 인증 코드로 확인됩니다.

   double Sum1= 0 ,Sum2= 0 ;
   ulong t= GetMicrosecondCount ();
   for ( int i= 0 ;i<ss;i++) Sum1+= sqrt ( double (i));   // Находим сумму квадратных корней всех целых чисел от 0 до ss
   t= GetMicrosecondCount ()-t;
   Print ( "Время на сумму " + IntegerToString (ss)+ " значений функций = " + IntegerToString (t)+ " мкс, Сумма = " + DoubleToString (Sum1));
   t= GetMicrosecondCount ();
   for ( int i= 0 ;i<ss;i++) Sum2+=SQRT[( int )(i)];     // Находим сумму квадратных корней всех целых чисел от 0 до ss через сложение элементов массива SQRT[]
   t= GetMicrosecondCount ()-t;
   Print ( "Время на сумму " + IntegerToString (ss)+ " значений массива = " + IntegerToString (t)+ " мкс, Сумма = " + DoubleToString (Sum2));

결과는 ~ 1.5배의 속도 증가를 나타냅니다.

그러나 코드의 sqrt() 함수를 SQRT[] 배열의 요소를 읽는 것으로 바꾸면 작업 속도를 높이는 대신 끔찍한 제동이 걸립니다.

SQRT[] 배열에서 요소를 읽는 것은 sqrt() 함수를 실행하는 것보다 몇 배나 더 오래 걸릴 수 있습니다.

그리고 나는 속도 누출이 어디에서 오는지 이해하지 못합니다. 결국 위의 인증 코드는 그렇지 않다고 말합니다.

컴파일러가 이상한 방식으로 큰 배열에 액세스하고 루프가 반복될 때마다 배열에 대해 "잊어버리는" 것처럼 보이고 매번 일종의 서비스 인덱싱을 수행한다고 가정할 수 있습니다.

그러나 이것은 내부 논리적 또는 전략적 컴파일러 버그입니다. 게다가, 이것으로 뭔가를 분명히 해야 하기 때문입니다. 이 속도 누출은 매우 중요하고 감지하기 어렵습니다. 그것은 분명하지 않습니다.

이 이상함을 보여주기 위해 스크립트 코드를 첨부합니다.

기본적으로(arr=false) 실행되면 sqrt() 함수가 평가되고 arr이 true로 변경되면 배열에서 제곱근 값을 가져옵니다.

뭐가 문제 야? 브레이크는 어디에서 왔습니까?

파일:
Swirl.mq5  11 kb
 
Nikolai Semko :

작업 속도를 높이기 위해 이 예제 를 만들 때 우연히 하나의 기이한 상황에 부딪쳤습니다.


SQRT[x] 배열에서 읽는 것이 sqrt(x) 함수보다 빠르다고 가정하는 것이 논리적 입니다.

동적 배열에서 사실이 아닙니다.

더욱이, 루트를 취하는 것은 오랫동안 SQRTSD 프로세서 명령 수준에 있었습니다. 즉, 동적 어레이의 악명 높은 액세스 비용 덕분에 더 이상 프로세서 구현을 능가할 수 없습니다.


그리고 이것은 인증 코드로 확인됩니다 .

결과는 ~ 1.5배의 속도 증가를 나타냅니다.

확인되었는지 의심스럽습니다.

이런 종류의 코드는 루프 최적화에 대한 교과서에서 바로 나온 것입니다. 코드 옵티마이저는 매우 간단하기 때문에 이것으로 무언가를 만들 수 있습니다.

   for ( int i= 0 ;i<ss;i++) 
      Sum2+=SQRT[i];

즉, 명백히 이상적으로 최적화된 케이스를 사용하는 경우의 성능 측정은 테스트의 목적과 명확하게 상관되어야 합니다.

이 경우 테스트가 잘못된 것입니다.

SQRT[] 배열에서 요소를 읽는 것은 sqrt() 함수를 실행하는 것보다 몇 배나 더 오래 걸릴 수 있습니다.

그리고 나는 속도 누출이 어디에서 오는지 이해하지 못합니다. 결국 위의 인증 코드는 그렇지 않다고 말합니다.

최종 어셈블러 코드를 보지 않고 다음과 같은 방향으로 기울고 있습니다.

  1. sqrt는 실제로 빠릅니다(네이티브 코드에 매우 효율적인 생성기가 있으며 sqrt는 순수한 SQRTSD로 바뀝니다)
  2. 검증 코드가 너무 간단하고 최적화로 지연을 보상합니다.


코드를 잘 확인해보자. 진짜 이유가 뭔지 알아가는 재미가 쏠쏠하다.

SQRTSD — Compute Square Root of Scalar Double-Precision Floating-Point Value
  • www.felixcloutier.com
Computes square root of the low double-precision floating-point value in xmm3/m64 and stores the results in xmm1 under writemask k1. Also, upper double-precision floating-point value (bits[127:64]) from xmm2 is copied to xmm1[127:64].
 
Renat Fatkhullin :

동적 배열에서 사실이 아닙니다.


최종 어셈블러 코드를 보지 않고 다음과 같은 방향으로 기울고 있습니다.

  1. sqrt는 실제로 빠릅니다(네이티브 코드에 매우 효율적인 생성기가 있으며 sqrt는 순수한 SQRTSD로 바뀝니다)
  2. 검증 코드가 너무 간단하고 최적화로 지연을 보상합니다.

정적 배열을 시도했습니다. 동일한 것입니다.

sqrt만큼 빠르지만 이 함수가 단순히 배열 요소 를 읽는 것보다 10배 더 빠를 수 있다고 믿기 어렵습니다.

또한 내 예에서 캔버스 크기가 50x50으로 축소된 경우(이 경우 입력 매개변수 크기가 있으므로 0 대신 50을 설정해야 함)

배열이 훨씬 작아지면(5000개 요소) 속도 그림이 눈에 띄게 바뀝니다. 더 이상 그렇게 강한 대조는 없습니다.

하지만 이해가 되지 않습니다. 요소에 대한 액세스 속도가 배열의 크기에 따라 달라지나요?

그리고 인증 코드의 단순성에 대해서는 아마도 당신이 옳을 것입니다.

나는 그것을 조금 복잡하게하려고 노력했고 결과는 완전히 다릅니다.

 for ( int i= 0 ;i<ss;i++) Sum1+= i* sqrt ( double (i));
....
for ( int i= 0 ;i<ss;i++) Sum2+= i* SQRT[( int )(i)];