루프 뒤 또는 루프 내부에서 변수를 선언하시겠습니까? - 페이지 2

 
Georgiy Merts :

아니요. 농담이 아냐.

물론 이 경우 일반 컴파일러는 루프 내에서 변수 선언을 제거해야 합니다.

나는 단지 "컴파일러에 대한 희망이지만 스스로 실수하지 마십시오."라고 생각합니다. 컴파일러 표준에서는 지역 변수가 선언 시 생성되고 선언된 블록이 종료되면 삭제된다고 가정합니다. 따라서 이 원칙은 처음부터 안내되어야 하며 컴파일러가 코드를 개선할 때까지 기다리지 않아야 합니다.

따라서 "실수하지 않으려면" 어셈블러로 이동하십시오. 모든 것을 직접 제어해야하기 때문에 ... 결국 설명 된 사례는 완전한 사소한 일입니다. 훨씬 더 복잡한 것들이 있습니다. OOP는 확실히 금기입니다. 컴파일러가 이 또는 저 가상 메서드를 일반 호출로 퇴화시켰는지, 아니면 불필요한 포인터 검사 를 생략했는지 알 수 없습니다. 그런 편집증이 있는 관리형 MQL에서 무엇을 할 수 있습니까? )

그리고 코드를 컴파일러의 기능(그리고 가상의 것)에 맞게 조정하여 코드의 정확성과 신뢰성을 손상시키는 것 - 이것은 분명히 훌륭한 프로그래머가 해서는 안 되는 일입니다. 그리고 여기서 우리는 코드의 부정확성에 대해 이야기하고 있습니다. 변수는 사용되는 블록에서 직접 선언해야 합니다.

 
Vict :

젠장, 글쎄, 이것은 단지 거친 밀도, 논평할 것이 있는 것, 디버거에 대한 완전한 오해입니다.

당신은 - 예.
 
Alexey Navoykov :
당신은 - 예.

유치원에서와 같이)) 탱크에 있는 사람들을 위해 설명합니다. 먼저 g++ 1.cpp를 컴파일하고 중단점이 없으며 컴파일러는 이에 대해 아무것도 모릅니다. 그런 다음 디버거를 시작합니다: gdb a.out, 그리고 이제서야 중단점을 설정합니다 .

그들이 무슨 말도 안되는 말을했는지 이해합니까?

 
Alexey Navoykov :

최적화는 컴파일된 코드나 성능 측정을 통해서만 감지할 수 있습니다. 그래서 이것이 가장 먼저 할 일입니다. 그리고 진정해)

2019.08.18 10:28:12.826 속도 테스트(EURUSD,H1) 1. s1=rand(): 루프=100000000ms=7031

2019.08.18 10:28:19.885 속도 테스트(EURUSD,H1) 2. s2=rand(): 루프=100000000ms=7063

2019.08.18 10:28:27.037 속도 테스트(EURUSD,H1) 3. s3=rand(): 루프=100000000ms=7140

2019.08.18 10:28:34.045 속도 테스트(EURUSD,H1) 4. s4=rand(): 루프=100000000ms=7016

2019.08.18 10:28:41.135 속도 테스트(EURUSD,H1) 5. s5=rand(): 루프=100000000ms=7094

2019.08.18 10:28:47.896 속도 테스트(EURUSD,H1) 1. q=rand(): 루프=100000000ms=6750

2019.08.18 10:28:54.659 속도 테스트(EURUSD,H1) 2. q=rand(): 루프=100000000ms=6765

2019.08.18 10:29:01.447 속도 테스트(EURUSD,H1) 3. q=rand(): 루프=100000000ms=6797

2019.08.18 10:29:08.257 속도 테스트(EURUSD,H1) 4. q=rand(): 루프=100000000ms=6797

2019.08.18 10:29:15.102 속도 테스트(EURUSD,H1) 5. q=rand(): 루프=100000000ms=6844

 //+------------------------------------------------------------------+
//|                                                    SpeedTest.mq5 |
//|                                                            IgorM |
//|                              https://www.mql5.com/ru/users/igorm |
//+------------------------------------------------------------------+
#property copyright "IgorM"
#property link        "https://www.mql5.com/ru/users/igorm"
#property version    "1.00"
#define N 8

#define   test(M,S,EX) { uint mss= GetTickCount (); ulong nn=( ulong ) pow ( 10 ,M); for ( ulong tst= 0 ;tst<nn&&! _StopFlag ;tst++){EX;} \
                         printf ( "%s: loops=%i ms=%u" ,S,nn, GetTickCount ()-mss);}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart ()
  {
   string s1; srand ( GetTickCount ()); test(N, "1. s1=rand()" ,s1= IntegerToString ( rand ()));
   string s2; srand ( GetTickCount ()); test(N, "2. s2=rand()" ,s2= IntegerToString ( rand ()));
   string s3; srand ( GetTickCount ()); test(N, "3. s3=rand()" ,s3= IntegerToString ( rand ()));
   string s4; srand ( GetTickCount ()); test(N, "4. s4=rand()" ,s4= IntegerToString ( rand ()));
   string s5; srand ( GetTickCount ()); test(N, "5. s5=rand()" ,s5= IntegerToString ( rand ()));

   srand ( GetTickCount ()); test(N, "1. q=rand()" , string q= IntegerToString ( rand ()));
   srand ( GetTickCount ()); test(N, "2. q=rand()" , string q= IntegerToString ( rand ()));
   srand ( GetTickCount ()); test(N, "3. q=rand()" , string q= IntegerToString ( rand ()));
   srand ( GetTickCount ()); test(N, "4. q=rand()" , string q= IntegerToString ( rand ()));
   srand ( GetTickCount ()); test(N, "5. q=rand()" , string q= IntegerToString ( rand ()));
  }
//+------------------------------------------------------------------+
 
디버거에서 비슷한 코드를 팠지만 사용자 연산자가 없으면 새롭지 않다는 몇 가지 의심이 있을 수 있습니다. 사용자 연산자가 최적화되지 않았다고 합니다. libc에서 malloc() 호출 잡기. 결과: 루프의 문자열 - 루프 외부에서 각 인쇄 전에 malloc에 대한 호출 - 많은 인쇄 전에 한 번 호출. 더 이상 의심의 여지가 없습니다. 첫 번째 옵션만 사용하는 것이 좋습니다. 물론 마이크로 리터로 다른 것이 가능하지만 성인 언어에 중점을 두는 것이 좋습니다.
 
#define N 9

2019.08.18 10:37:59.620 속도 테스트(EURUSD,H1) 1. s1=rand(): 루프=1000000000ms=70672

2019.08.18 10:39:10.352 속도 테스트(EURUSD,H1) 2. s2=rand(): 루프=1000000000ms=70719

2019.08.18 10:40:21.908 속도 테스트(EURUSD,H1) 3. s3=rand(): 루프=1000000000ms=71562

2019.08.18 10:41:32.315 속도 테스트(EURUSD,H1) 4. s4=rand(): 루프=1000000000ms=70407

2019.08.18 10:42:42.996 속도 테스트(EURUSD,H1) 5. s5=rand(): 루프=1000000000ms=70687

2019.08.18 10:43:50.964 속도 테스트(EURUSD,H1) 1. q=rand(): 루프=1000000000ms=67969

2019.08.18 10:44:58.887 속도 테스트(EURUSD,H1) 2. q=rand(): 루프=1000000000ms=67922

2019.08.18 10:46:06.829 속도 테스트(EURUSD,H1) 3. q=rand(): 루프=1000000000ms=67937

2019.08.18 10:47:14.602 속도 테스트(EURUSD,H1) 4. q=rand(): 루프=1000000000ms=67766

2019.08.18 10:48:22.428 속도 테스트(EURUSD,H1) 5. q=rand(): 루프=1000000000ms=67828

 

Igor Makanu:

 #define   test(M,S,EX) { uint mss= GetTickCount (); ulong nn=( ulong ) pow ( 10 ,M); for ( ulong tst= 0 ;tst<nn&&! _StopFlag ;tst++){EX;} \

젠장, 스페이스 바가 작동하지 않습니다 chtol? ) 처음 알아차린 것은 아닙니다. 아니면 하드 드라이브에 바이트를 저장하시겠습니까? )

 
Alexey Navoykov :

장난해? 이것은 컴파일러에게 너무 사소한 상황이어서 여기에서 말할 것도 없습니다. 그리고 그런 편집증으로 순전히 어셈블러에서 인코딩할 수 있습니다.) 비록 이것이 지금 현재로서는 이미 무의미해지고 있지만. 최신 컴파일러의 최적화를 능가하려면 매우 열심히 노력해야 합니다.

ps 아마도 나는 이 경우의 사소함에 약간 흥분했을 것입니다. 우리는 문자열 버퍼 에 대해 이야기하고 있습니다. 그러나 MQL에 저장되는 것은 보장됩니다. 루프 내부뿐만 아니라 함수 호출 사이에도 마찬가지입니다. 이 주제는 여기에서 여러 번 논의되었습니다.

이 진술의 작성자가 프로세서, 메모리 및 컴파일러가 어떻게 작동하는지 전혀 모르고 있다는 의심이 듭니다... 저는 귀하의 코드가 적어도 수십 배, 심지어 수백 배까지 가속화될 수 있다고 확신합니다. 그런 엉터리 코더 때문에 대부분의 제품은 이제 수십 개의 코어가 있는 가장 강력한 컴퓨터에서 뻔뻔하게 속도가 느려지지만 조금만 생각하면 됩니다. 하지만 어떤 사람들은 생각합니다.

참고로 현재로서는 어떤 컴파일러도 프로그래머가 결과적으로 얻고자 하는 것을 이해하는 법을 배우지 못했습니다. 일부 루프를 풀고 일부 메모리 액세스를 최적화하여 데이터가 프로세서 캐시에 있도록 할 수 있지만 코드가 처음에 최적화되어 한 곳을 통해 작성되지 않으면 컴파일러가 도움이되지 않습니다 ...

PS 여가 시간에 Chris Kaspersky의 재미있는 작은 책 읽기 " 프로그램 최적화 기술. 메모리의 효율적인 사용"

 
Alexey Volchanskiy :

조지의 말이 맞아요, 보장되지는 않습니다.

그리고 우리는 '숫자'에서 '문자열'로의 암시적 변환 경고를 받습니다.


그리고 이것이 바로 우리가 불확실성과 경고를 제거하는 방법입니다

 for ( int i = 0 ; i < 1000 ; i++)
   {
       static string st = IntegerToString (i);
      ...
   }

그리고 나는 항상 이것을 해왔습니다.

 string st = ( string )i;

그리고 왜 정적입니까? 할당은 한 번만 첫 번째 반복에서 작동합니다.


실행 속도를 측정하기로 결정

   CStopWatch sw; // Секундомер, для замера времени
   
   sw.Start();
   for ( int i = 0 ; i < 10000000 ; i++)
   {
       string st = ( string )i;
   }
   pr( "Test1, время выполнения: " + sw.Stop());

   sw.Start();
   string st = "" ;
   for ( int i = 0 ; i < 10000000 ; i++)
   {
      st = ( string )i;
   }
   pr( "Test2, Время выполнения: " + sw.Stop());

결과:

Test1, время выполнения: 0.548275 сек.
Test2, Время выполнения: 0.313978 сек.

여러 번 실행하면 결과가 안정적이고 루프 뒤에변수가 선언 된 코드가 더 빠르게 작동합니다.

 
Alexey Navoykov :

젠장, 스페이스 바가 작동하지 않습니다 chtol? ) 처음 알아차린 것은 아닙니다. 아니면 하드 드라이브에 바이트를 저장하시겠습니까? )

아니요, 이 코드는 제 것이 아닙니다. 조금 빗질했습니다. "소수점 자릿수 검색"에 대한 주제에서 직접 코드를 복사했으며 논쟁의 여지가 있는 문제에 사용합니다. 편집하기에는 너무 게으릅니다.

일반적으로 나는 간격이 있고 게으름이 있습니다.))))

추신 : 나에게 모범적인 코드를 주시면 내가 직접 복사할 것입니다. 앞으로 원하는 대로 될 것입니다. 원칙적으로 이것은 저를 괴롭히지 않습니다.

추신: 여기:

 #define   test(M,S,EX) {                                 \
uint mss= GetTickCount ();                                 \
ulong nn=( ulong ) pow ( 10 ,M);                               \
for ( ulong tst= 0 ;tst<nn && ! _StopFlag ;tst++) \
{ EX; }                                                  \
printf ( "%s: loops=%i ms=%u" ,S,nn, GetTickCount ()-mss);}