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

 
Georgiy Merts:

いいえ、そうではありません。

確かに、この場合の通常のコンパイラは、ループ内の変数宣言を外部に持ってくるはずです。

ただ、常にコンパイラーを信頼し、自分自身を信頼するべきだと思います。ローカル変数は宣言されたときに作成され、宣言されたブロックが終了したときに削除されるのがコンパイラの標準である。ですから、コンパイラがあなたのためにコードを改善してくれるのを待つのではなく、そもそもこの原則に注目すべきなのです。

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

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

 
Vict:

まーた野暮なこと言って、何がコメントだ、デバッガの仕組みを全く理解してないのか。

そうなんですね。
 
Alexey Navoykov:
そうなんですね。

幼稚園の時のように )))まず、g++ 1.cppをコンパイルすると、そこにはブレークポイントがなく、コンパイラはブレークポイントについて何も知らない。次にデバッガを実行します:gdb a.out、そして今だけブレークポイントを 置きます。

自分が何を言ったか理解してる?

 
Alexey Navoykov:

コンパイルや性能測定をして初めて最適化がわかる。 それが最初にやるべきことです。そして落ち着く )

2019.08.18 10:28:12.826 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7031

2019.08.18 10:28:19.885 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7063

2019.08.18 10:28:27.037 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7140

2019.08.18 10:28:34.045 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7016

2019.08.18 10:28:41.135 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7094

2019.08.18 10:28:47.896 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=6750

2019.08.18 10:28:54.659 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=6765

2019.08.18 10:29:01.447 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:08.257 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:15.102 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=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() の呼び出しを捕捉した。結果:ループ内の文字列-各印刷の前に1回呼び出し、ループ外-印刷のバッチの前に1回呼び出し。間違いなく、最初のバリエーションだけが優れているのです。もちろん、µlでは何かが違うという可能性もありますが、成熟した言語から導かれるのが良いのでしょう。
 
#define  N 9

2019.08.18 10:37:59.620 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=1000000000 ms=70672

2019.08.18 10:39:10.352 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=1000000000 ms=70719

2019.08.18 10:40:21.908 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=1000000000 ms=71562

2019.08.18 10:41:32.315 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=1000000000 ms=70407

2019.08.18 10:42:42.996 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=1000000000 ms=70687

2019.08.18 10:43:50.964 SpeedTest (EURUSD,H1) 1. q=rand(): loops=1000000000 ms=67969

2019.08.18 10:44:58.887 SpeedTest (EURUSD,H1) 2. q=rand(): loops=1000000000 ms=67922

2019.08.18 10:46:06.829 SpeedTest (EURUSD,H1) 3. q=rand(): loops=1000000000 ms=67937

2019.08.18 10:47:14.602 SpeedTest (EURUSD,H1) 4. q=rand(): loops=1000000000 ms=67766

2019.08.18 10:48:22.428 SpeedTest (EURUSD,H1) 5. q=rand(): loops=1000000000 ms=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;} \

男、「スペースバー」が効かないのか?今に始まったことではありませんが。 それとも、ハードディスクにバイトを保存しているのでしょうか?)

 
Alexey Navoykov:

コンパイラにとっては、そんなことはどうでもいいことなのです。 そんなことを気にしながら、純粋にアセンブラでコードを書けばいいのです。 もっとも、それも最近は無意味になってきていますが。 最近のコンパイラの最適化に勝つには、相当努力しなければならないでしょう。

p.s.文字列バッファの 場合の些細なことに少し興奮したのかもしれません。しかし、MQLではループ内だけでなく、関数呼び出しの間でも保存されることが保証されています。この話題は一度ならずここで取り上げられた

この文章の著者は、プロセッサ、メモリ、コンパイラの仕組みを全く知らないのでは...と勘ぐってしまう。あなたのコードなら、少なくとも10倍、あるいは数百倍は高速化できるはずです。 そんなクソコーダーのせいで、ほとんどの製品は、何十ものコアを持つ強力なコンピュータでは耐えられないほど遅くなってしまいましたが、あなたは少し考えるだけでいいのです...しかし、「なぜ考えるのか」と思う人もいます。コード化する必要がある..."

ちなみに、プログラマが結果として何を得たいのかを理解することを学んだコンパイラは、今のところ存在しない。ループをいくつかアンロールしたり、メモリアクセスを最適化してプロセッサのキャッシュにデータを残すことはできますが、もともと最適化されていないコードが一か所を通して書かれていると、どんなコンパイラも役に立ちません...。

追伸:クリス・カスペルスキー著の「プログラム最適化技術」という面白い本があるので、暇な時にでも読んでみてください。効率的なメモリー使用」。

 
Alexey Volchanskiy:

ジョルジュの言う通り、保証はない。

そして、'number' から 'string' へのワープ暗黙の変換を取得します。


それこそが、曖昧さやゆがみを解消する方法なのです。

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:

男、「スペースバー」が効かないのか?今に始まったことではありませんが。 それとも、ハードディスクにバイトを保存しているのでしょうか?)

いいえ、このコードは私のものではありません、私はそれを少し改良しました - 私は "セミコロンの検索 "についてのスレッドから自分自身のためのコードをコピーして、論争の質問にそれを使用して、私はそれを変更するにはあまりにも怠惰だ。

スペースがあるのにやるのが億劫で ))))

ZS: 私にモデルコードを与えて、それを自分にコピーして、将来あなたが望むようになります、私は原則的に、それは私を悩ますことはありません。

ZS: ここでAD :

#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);}