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

 

음수 값에 대한 최적화 그래프를 작성하지 않습니다.

최적화 결과에 데이터가 있습니다.

Expert Advisors에서 음수 값을 설정하십시오. 값은 유효성 검사를 위해 * -1이 될 수 있습니다.

 
Renat Fatkhullin :

확인 결과:

  1. 직접 CPU 명령어에 매핑된 SQRT

  2. SQRT + 수학적 계산 은 분기 없이 진행되며 하나의 명령(128비트 데이터)에 대해 두 개의 근이 한 번에 계산됩니다.

    이 코드는 다음 어셈블러 SSE 코드로 바뀝니다.
    이것은 결국 예술 작품입니다. 어셈블러 명령어의 4번 호출에 대해 8개의 루트가 계산됩니다. 한 번의 호출로 두 개의 이중 숫자가 계산되었습니다.

  3. 배열을 통한 작업 중에 이중 -> 정수 인덱스 변환에 대한 검사, 분기 및 손실과 함께 모든 것이 정상적으로 진행됩니다.

  4. 이 예에서 어레이로 작업할 때 FPU/ALU가 지속적으로 혼합되어 성능에 매우 나쁜 영향을 미칩니다.

  5. 동적 어레이에 대한 액세스 최적화는 칭찬을 넘어 탁월합니다. 그러나 FPU/ALU 연산을 혼합 + 이중 변환 -> 정수 + 분기는 시간을 낭비합니다.

일반적인 결론: MQL5의 수학은 완벽한 최적화 덕분에 승리했습니다. 지는 것은 배열이 아니라 수학이 이깁니다.

소중한 정보 정말 감사합니다.

물론 더 기쁜 소식입니다. 정말 멋지다!

MQ는 항상 잘생겼다고 말했어요!

그러나 데이터 유형을 혼합할 때 매우 조심해야 한다는 것도 이해합니다. 그러나 미리 경고합니다.
이러한 관점에서 개발자로부터 몇 가지 권장 사항을 얻는 것이 좋습니다.

이제 일반 변수와 배열의 유형을 모두 실험해 보겠습니다. 어떤 일이 일어나는지 흥미롭습니다.

 
Renat Fatkhullin :

실험했습니다.

어쩐지 내 퍼즐이 맞지 않아.

두 가지 옵션을 만들었습니다. 첫 번째 - 최대로 모든 것을 int 유형 으로 전송했습니다. 두 번째는 더블입니다.

네, 조금 빨라졌습니다. 그러나 메인 브레이크는 여전히 존재합니다.

다음은 int 옵션이 있는 메인 브레이크 블록입니다.

 if (arr)
        {   // расчет квадратных корней через массив значений SQRT[]
         D1=SQRT[((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))];
         D2=SQRT[((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y))];
         D3=SQRT[((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y))];
         D4=SQRT[((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y))];
         D5=SQRT[((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y))];
         D6=SQRT[((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y))];
         D7=SQRT[((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y))];
         D8=SQRT[((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y))];
        }

int 유형만 있고 유형 혼합이 없습니다. 동시에 SQRT 배열 자체가 int가 되었습니다.

10%만 더 빠르게 작동합니다.

C 변종은 유사한 그림을 두 배로 만듭니다.

글쎄, 모든 것이 동일합니다. 한 가지 경우에만 sqrt() 함수가 계산되고 유형이 혼합되어 있습니다.

그리고 두 번째 경우에는 int 배열에 접근하여 type 믹싱이 없고 이론상 ALU만 사용해야 합니다.

그리고 두 번째 옵션은 3배 느립니다. 글쎄요, 누가 뭐라고 해도 그 이유는 배열입니다.

그리고 한 가지 더 중요한 점.

int 예제에서 캔버스가 100x100인 경우, 즉 이 설정으로

그런 다음 어레이에 액세스할 때 속도가 향상됩니다.

저것들. 크기가 20,000인 SQRT 배열을 사용할 때 15-20%의 승리를 거두고 3,000,000을 사용할 때 정확히 동일한 수학으로 200%를 잃습니다.

어레이의 크기가 브레이크의 이유입니까?

파일:
LSD_double.mq5  10 kb
LSD_int.mq5  10 kb
 

사람들은 현대 C++ 컴파일러의 출력을 이해하는 능력을 오랫동안 상실했습니다.

또한 코드에서 vinaigrette/garbage가 있습니다. 이는 "만약 그러한 조건이 있다면 결과는 이와 같을 것"이라는 순진한 공리를 구축할 기회가 거의 없음을 의미합니다. 즉, 최종 최적화는 코드가 조금만 변경되더라도 가설이 수십 퍼센트 다른 결과를 제공할 정도로 모든 것을 다시 빌드합니다.

8개의 루트를 4개의 어셈블러 명령으로 압축한 것을 다시 한 번 살펴보고 논리를 주장하거나 요구하거나 호소할 기회가 없음을 이해하십시오. 옵티마이저는 오랫동안 프로그래머가 접근할 수 없는 초월적인 수준에서 작업해 왔습니다.

컴파일러가 루트를 분해하는 방식은 예술입니다. 그리고 가장 단순한 제한도 이해하지 못한 채 어레이로 이를 이기려고 합니다. 어레이에서 읽는 것은 이미 실패입니다. 완벽한 레지스터 작업 및 일괄 루트 대 분기(페널티) 및 빈번한 캐시 누락으로 인한 메모리 상승.

프로세서의 L1 / L2 / L3 캐시에 대해 전혀 모르기 때문에 "작은 버퍼에서는 더 빠르게 작동하지만 큰 버퍼에서는 귀청이 날 정도로 병합되는 이유"라는 질문을 합니다. 캐시 히트 - 빠르게 계산됩니다. 히트하지 않음 - 상위 캐시 또는 메모리에서 데이터를 읽는 데 수십 주기를 기다립니다.
 
Renat Fatkhullin :

사람들은 현대 C++ 컴파일러의 출력을 이해하는 능력을 오랫동안 상실했습니다.

또한 코드에서 vinaigrette/garbage가 있습니다. 이는 "만약 그러한 조건이 있다면 결과는 이와 같을 것"이라는 순진한 공리를 구축할 기회가 거의 없음을 의미합니다. 즉, 최종 최적화는 코드가 조금만 변경되더라도 가설이 수십 퍼센트 다른 결과를 제공할 정도로 모든 것을 다시 빌드합니다.

8개의 루트를 4개의 어셈블러 명령으로 압축한 것을 다시 한 번 살펴보고 논리를 주장하거나 요구하거나 호소할 기회가 없음을 이해하십시오. 옵티마이저는 오랫동안 프로그래머가 접근할 수 없는 초월적인 수준에서 작업해 왔습니다.

VS와의 비교 결과를 매우 잘 볼 수 있으며 매우 기쁩니다.
그러나 질문은 여전히 열려 있습니다.

혼란스러운 작업 코드에 대해 사과하지만 이것은 코드의 이 섹션과 두 가지 실행 옵션을 비교하는 것에 관한 것입니다.

 if (arr)
        {   // расчет квадратных корней через массив значений SQRT[]
         D1=SQRT[((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))];
         D2=SQRT[((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y))];
         D3=SQRT[((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y))];
         D4=SQRT[((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y))];
         D5=SQRT[((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y))];
         D6=SQRT[((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y))];
         D7=SQRT[((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y))];
         D8=SQRT[((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y))];
        }
 else // расчет квадратных корней через функцию кв. корня sqrt()
        {
         D1=( int ) sqrt ((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y));
         D2=( int ) sqrt ((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y));
         D3=( int ) sqrt ((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y));
         D4=( int ) sqrt ((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y));
         D5=( int ) sqrt ((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y));
         D6=( int ) sqrt ((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y));
         D7=( int ) sqrt ((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y));
         D8=( int ) sqrt ((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y));
        }

여기에는 쓰레기가 없습니다.

" 동적 어레이 접근 최적화는 칭찬을 넘어 탁월하다"고 말씀하셨습니다.

하지만... 내 이전 게시물을 참조하십시오.

내 마지막 실험을 어떻게 설명하시겠습니까?:

"즉, 크기가 20,000인 SQRT 배열을 사용하면 15~20%의 승리를 거두고 3,000,000을 사용하면 정확히 같은 수학으로 200%를 잃습니다.

어레이의 크기가 브레이크의 이유입니까?"

 

내 이전 답변을주의 깊게 읽으십시오 - 정확한 답변과 함께 추가되었습니다.

귀하의 질문을 간단하게 설명하겠습니다. 성능 및 영향을 미치는 요인 측면에서 프로세서 설계에 대한 5가지 기술 문서를 주의 깊게 읽으십시오. 그것 없이는 당신이 기본적인 것들을 설명해야 하기 때문에 당신은 토론을 할 수 없습니다.

 
Renat Fatkhullin :

컴파일러가 루트를 분해하는 방식은 예술입니다. 그리고 가장 단순한 제한도 이해하지 못한 채 어레이로 이를 이기려고 합니다. 어레이에서 읽는 것은 이미 실패입니다. 완벽한 레지스터 작업 및 일괄 루트 대 분기(페널티) 및 빈번한 캐시 누락으로 인한 메모리 상승.

프로세서의 L1 / L2 / L3 캐시에 대해 전혀 모르기 때문에 "작은 버퍼에서는 더 빠르게 작동하지만 큰 버퍼에서는 귀청이 날 정도로 병합되는 이유"라는 질문을 합니다. 캐시 히트 - 빠르게 계산됩니다. 히트하지 않음 - 상위 캐시 또는 메모리에서 데이터를 읽는 수십 주기 동안 기다립니다.
레나트 팻쿨린 :

내 이전 답변을주의 깊게 읽으십시오 - 정확한 답변과 함께 추가되었습니다.

귀하의 질문을 간단하게 설명하겠습니다. 성능 및 영향을 미치는 요인 측면에서 프로세서 설계에 대한 5가지 기술 문서를 주의 깊게 읽으십시오. 그것 없이는 당신이 기본적인 것들을 설명해야 하기 때문에 당신은 토론을 할 수 없습니다.

만세!!!
드디어!
레나트, 너에게서 모든 것은 집게로 뽑아야 한다.

이제 그림이 더 명확해졌습니다.

내가 그것을 당신의 컴파일러로 몰았을 때 틀렸습니다. 고백합니다. 악마가 속았습니다. 그 이유는 프로세서의 제한된 캐시 때문일 수 있습니다. 나는 현대 프로세서에 대해 정말 서툴고 그것에 대해 읽어야 합니다.

하지만 내가 이 코드를 작성한 것은 헛된 것이 아닙니다.

따라서 이 주제를 읽는 프로그래머를 위해 이 물결의 결과로 개인적으로 알아낸 것을 요약하겠습니다.

  • sqrt() 함수와 다른 많은 기본 함수는 매우 빠르며 컴파일러 수준이 아니라 프로세서 수준에서 실행됩니다.
  • MQL5 컴파일러는 수학적 논리를 최적화하는 데 매우 강력하여 최신 VS C++ 컴파일러가 쉽게 수행할 수 있습니다. 매우 고무적입니다.
  • 리소스 집약적인 작업에서는 유형을 혼합하지 않는 것이 좋습니다. 유형을 혼합하면 계산 속도가 느려집니다.
  • 크기가 중요합니다! (배열의 크기를 의미합니다 :)) 다단계 프로세서 캐시 의 특성과 제한된 크기 때문입니다. 그리고 프로그래머가 배열의 총 크기를 추적하고 큰 배열을 사용하면 계산 속도에 상당한 영향을 미칠 수 있다는 것을 이해하는 것은 불필요한 일이 아닙니다. 내가 이해하는 한, 우리는 약 512kB를 초과하지 않는 총 볼륨을 가진 어레이의 비교적 편안한 작동에 대해 이야기하고 있습니다. 이는 이중 유형의 ~65000개 요소 또는 int 유형의 ~130000개 요소입니다.

이 정보에서 진행 중인 코드를 수정하기 위해 이동했습니다. 나는 종종 배열의 크기를 남용했습니다.

모두 감사합니다!

 

십자형 버튼을 눌렀는지 떼었는지 어떻게 알 수 있습니까?

마우스 휠의 클릭을 잡을 수 있지만 마우스를 사용하지 않으면 어떻게해야합니까?

 
Alexandr Bryzgalov :

십자형 버튼을 눌렀는지 떼었는지 어떻게 알 수 있습니까?

마우스 휠의 클릭을 잡을 수 있지만 마우스를 사용하지 않으면 어떻게해야합니까?

필요한 경우 강제로 누르거나 짜낼 수 있습니까?

CHART_CROSSHAIR_TOOL

마우스 가운데 버튼을 눌러 "십자선" 도구에 대한 액세스를 활성화/비활성화합니다.

bool(기본값 true)

 
Alexey Viktorov :

필요한 경우 강제로 누르거나 짜낼 수 있습니까?

CHART_CROSSHAIR_TOOL

마우스 가운데 버튼을 눌러 "십자선" 도구에 대한 액세스를 활성화/비활성화합니다.

bool(기본값 true)

내가 이해하는 한 이것은 도구에 대한 액세스일 뿐 끄지는 않습니다.

사유: