[解決済み] while (1) Vs. for (;;) 速度差はあるのか?
質問
ロングバージョン...
の使い方を見て、同僚が断言しました。
while (1)
はPerlスクリプトで
for (;;)
の方が速い。 私は、インタープリタがその違いを最適化してくれることを期待して、両者は同じであるべきだと主張しました。そこで、1,000,000,000回のforループと同じ回数のwhileループを実行し、その間の時間を記録するスクリプトを作成しました。その結果、有意な差は見つからなかった。私の同僚は、ある教授から
while (1)
は比較をしていた
1 == 1
と、その
for (;;)
はなかった。 C++で100倍の反復計算をして同じテストを繰り返しましたが、その差はごくわずかでした。しかし、コンパイルされたコードがスクリプト言語に比べてどれだけ高速化できるかを示す、画期的な例となりました。
ショートバージョン...
を好む理由はあるのでしょうか?
while (1)
の上に
for (;;)
無限ループから抜け出したい場合は?
注意してください。 質問からわからないのであれば これは純粋に友人カップルの楽しい学問的な議論でした。 すべてのプログラマーが悩むような超重要なコンセプトではないことは承知しています。 この議論から私は(そしてきっと他の人も)いくつかのことを学んだと思います。
更新しました。 前述の同僚は、以下のように回答しています。
埋もれてしまうかもしれないので、ここに引用しておきます。
<ブロッククオート
AMDのアセンブリプログラマーからの情報です。彼は、Cプログラマーは
(そのコードが非効率的であることに気づいていないのです。彼はこう言っています。
しかし、現在ではgccコンパイラが非常に優秀で、彼のような人を排除しています。
ということです。例えば、と言って教えてくれたのは
while 1
対
for(;;)
. 今は習慣的に使っていますが、gccや特にインタプリタでは
は、最近はどちらも同じ操作(プロセッサジャンプ)をしてくれます。
最適化されているからです。
解決方法は?
perlでは、同じopcodeになります。
$ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
9 <2> leaveloop vK/2 ->a
3 <{> enterloop(next->8 last->9 redo->4) v ->4
- <@> lineseq vK ->9
4 <;> nextstate(main 1 -e:1) v ->5
7 <@> print vK ->8
5 <0> pushmark s ->6
6 <$> const[PV "foo\n"] s ->7
8 <0> unstack v ->4
-e syntax OK
$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
9 <2> leaveloop vK/2 ->a
3 <{> enterloop(next->8 last->9 redo->4) v ->4
- <@> lineseq vK ->9
4 <;> nextstate(main 1 -e:1) v ->5
7 <@> print vK ->8
5 <0> pushmark s ->6
6 <$> const[PV "foo\n"] s ->7
8 <0> unstack v ->4
-e syntax OK
同様にGCCでも。
#include <stdio.h>
void t_while() {
while(1)
printf("foo\n");
}
void t_for() {
for(;;)
printf("foo\n");
}
.file "test.c"
.section .rodata
.LC0:
.string "foo"
.text
.globl t_while
.type t_while, @function
t_while:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
.L2:
movl $.LC0, %edi
call puts
jmp .L2
.LFE2:
.size t_while, .-t_while
.globl t_for
.type t_for, @function
t_for:
.LFB3:
pushq %rbp
.LCFI2:
movq %rsp, %rbp
.LCFI3:
.L5:
movl $.LC0, %edi
call puts
jmp .L5
.LFE3:
.size t_for, .-t_for
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long .LASFDE3-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI2-.LFB3
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI3-.LCFI2
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE3:
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
つまり、多くのコンパイラで同じということですね。もちろん、他のコンパイラでは必ずしもそうではないかもしれませんが、ループの中のコードはループ自体よりも数千倍も高価になる可能性がありますから、誰が気にするでしょうか?
関連
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] \0-9]よりも効率が悪い
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複