ループの後ろで変数を宣言するのか、ループの中で宣言するのか? - ページ 4

 

プロジェクトの 設定で最適化がオフになっています。

コード

   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 сек.

最適化により

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

最適化ではその逆で、何度も確認しました。

 
Aleksandr Matveev:

まず基本を学んでから、自分の主張を証明すべきです。CPUやメモリの操作に関する本を一冊でも読んでいれば、何もテストしなくても結果がわかるはずです。最も工夫されたものを提供しましたので、プログラミングを少し進めたい方はぜひ読んでみてください。

メモリとCPUは関係あるのか? 最適化の話だろ、本末転倒な理論家だな)。

 
Igor Makanu:

MQLの最も単純な演算子や操作をテストできるようにする必要があります。?

;)

ところで、よく見てください。ループ の中の結果は何も考慮されていません。つまり、コンパイラで簡単にカットすることができるのです。

 
Alexey Navoykov:

ちなみに、よく見たら、ループ の結果は何も考慮されていないので、コンパイラは簡単にカットできますね。

rand() も削除 - そのコンパイラは完全にそれをインライン化し、そのようなテストを行いました。

#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;  test(N,"1. s1=rand()",s1=(string)tst);
   string s2;  test(N,"2. s2=rand()",s2=(string)tst);
   string s3;  test(N,"3. s3=rand()",s3=(string)tst);
   string s4;  test(N,"4. s4=rand()",s4=(string)tst);
   string s5;  test(N,"5. s5=rand()",s5=(string)tst);

   test(N,"1. q=rand()",string q=(string)tst);
   test(N,"2. q=rand()",string q=(string)tst);
   test(N,"3. q=rand()",string q=(string)tst);
   test(N,"4. q=rand()",string q=(string)tst);
   test(N,"5. q=rand()",string q=(string)tst);
  }
//+------------------------------------------------------------------+

2019.08.18 11:55:41.457 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7672

2019.08.18 11:55:49.085 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7625

2019.08.18 11:55:56.796 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7719

2019.08.18 11:56:04.495 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7703

2019.08.18 11:56:12.113 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7610

2019.08.18 11:56:17.695 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=5578

2019.08.18 11:56:23.362 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=5672

2019.08.18 11:56:28.970 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=5609

2019.08.18 11:56:34.637 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=5672

2019.08.18 11:56:40.277 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=5640


 
Alexey Navoykov:

だから、「ちゃんとやりたい」ならアセンブラにしろ、「自分で全部コントロールしたい」なら......と言っているんです。結局、今お話に出たようなケースはまったくないんです。もっと複雑な事情があるのですが、OOPはあなたにとって間違いなく禁忌です。コンパイラが特定の仮想メソッドを普通の呼び出しに退化させていないか、不要なポインタチェックをカットしていないか...そんなパラノイアで、マネージドMQLで何ができるんだ?)

また、コンパイラの特殊性(しかも架空のもの)に合わせてコードを調整し、コードの正確さや信頼性を損なうことは、明らかに優れたプログラマのすべきことではありません。 そして、ここではコードの不正確性について話しています。 変数は、それが使われるブロック内で直接宣言されなければならないのです。

はははは...。アレクセイ、あなたは(「あなた」としておきますが)フォーラムの主なOOP熟練者の一人に対して「OOPは絶対に禁忌だ」と主張していますね。

コードはコンパイラの特質に合わせるのではなく、オウンの考え方の特質に合わせるべき。この場合、理論的にはループ内部で変数を宣言 すると効率が悪くなる。なぜなら、規約上、変数はその都度作成し、その都度破棄しなければならないからです。

効率の問題でもない。ソリッドコードとは、透明で明確な、修正と保守が容易なコードのことです。

個人的には、たくさんの変数がプログラム中に散らばっていて、特定の変数がどこで作られたかを毎回探さなければならないのは好きではありません。 そのため、可能であれば関数の冒頭で、まとめて変数を宣言するようにしています。ただ、どこで変数が作られるのか、いつ削除されるのかがわかるようにするためです。

この場合、例が非常に短いだけです。変数の作成から使用までの間に何十行もの行や入れ子関数がある場合、私には、ブロックの外であらかじめ変数が宣言されている方がはるかに信頼性が高いのです。

 
pivalexander:

プロジェクトの設定で最適化がオフになっています。

コード


非最適化

最適化により

最適化では、そうですね、逆ですね、何度も確認しました。

あなたの例では、ループ本体全体を最適化で切り取ることができたはずです。

 

一般に、存在しない問題を探し、実在する問題を作り出すような無意味なことをする必要はないと、すべてが予想通りになっています。

かゆいところに手が届く、自分はクールなハッカーだと思うのなら、アセンブラで書くか、さもなければ、コンパイラに仕事をさせるように立ち回ればいいのです。

 
Aleksandr Matveev:

この例では、最適化によってループ本体全体をカットすることができたはずです。

ループ本体を空にして実行した結果は、全く異なり、より高速に動作する

Без оптимизации:
Test1, время выполнения: 0.027539 сек.

С оптимизацией:
Test1, время выполнения: 0.005448 сек.
 
Alexey Navoykov:

一般に、存在しない問題を探し、実在する問題を作り出すような無意味なことをする必要はないと、すべてが予想通りになっています。

もし、あなたがかゆいところに手が届く、クールなハッカーだと思うなら、アセンブラで書けばいいし、そうでないなら、コンパイラーに任せておけばいいのです。

一番の問題は、まさに自分がクールハッカーでないと思っていることです。そのため、変数はループの外で宣言するべきだと私は考えています。しかも、もっといいのは、機能の最初に、一度に。

そして、ただのクーリエは、コードの内部で、必要に応じて変数を宣言することができます。

 
Georgiy Merts:

一番の問題は、まさに自分がクールハッカーでないと思っていることです。だから変数は、ループの外で宣言するべきだと私は思う。 そして、できれば関数の最初に、一度に。

クールハッカーは、コード内で必要に応じて変数を宣言することができます。

私は、関数の最初にたくさんの変数を作成するよりも、コードを論理的なブロックに分割し、そのブロックの中で必要な変数を宣言することを好みますが、そのほとんどは、どこか遠く下のブロックで必要とされるだけなのです。