2013-04-28 8 views
6

条件を使用せずに特定の回数だけ繰り返してコードブロックを繰り返しています。基本的には固定数のコードブロックを繰り返します。

、このような何か:

repeat(50) 
{ 
    //Do stuff here. 
} 

これを行う方法はありますか? 50回コピーして貼り付ける以外は?

私は何回繰り返したいのか分かっているので、毎回条件を確認するよりも早くなると思ったので、これをやっています。それは正確ですか?それとも、何度繰り返しているのか、まだチェックしていますか?

基本的に、それはもっと速いですか?

+0

ハードリピートをお探しですか?コードの50回の実行と同じ* s * *任意の*条件? – WhozCraig

+1

私が知る限り、コンパイラは、そのコードをx回書いたのと同じ結果のコードにリテラルサイズ(変数ではない)を使ってforループを最適化することがよくあります。したがって、 'repeat(50)'は 'for(char i = 0; i <50; i ++)と同じです(' char 'を使用しています。 'char'の場合は1だけです)。 –

+0

@MrUniverse偉大な、ありがとう、ちょうど私が必要なもの。 – Serdnad

答えて

10

ループの実行速度を最適化するために、いくつかの構造体(コードを貼り付ける手動での削除を含む)を使用してループを最適化しようとすると、お勧めできません。しないでください。おそらく実行速度を "最適化しない"でしょう。

MSVC 6.0,2003,2005,2010、GCCの様々なバージョン、Diabの様々なバージョン)で遭遇したC++の実装では、絶対にゼロです。申し訳ありませんが、私は十分にストレスを感じませんでした。ループカウント変数が割り当てられた関数に他の変数が割り当てられていると仮定して、ループカウント変数を割り当てます。関数呼び出しをしない単純なループの場合、ループカウント変数は決してメモリにそれを出さないかもしれません。それはその全寿命の間、単一のCPUレジスタ内に完全に保持されてもよい。たとえそれがメモリに格納されていても、それはランタイムスタック上にあり、そのためのスペース(および他のローカル変数)は、一度に1回の操作ですべて要求されます。スタックに割り当てられた変数。ループカウンター変数のようなローカル変数はスタックに割り当てられ、スタック割り当てはヒープ割り当てではなく、CHEAP CHEAP CHEAPです。スタック上の

例のループカウンタ変数割当:

for (int i=0; i<50; ++i) { 
    .... 
} 

スタック上の他の例のループカウンタ変数割当:ヒープ上に割り当てられ

int i = 0; 
for (; i<50; ++i) { 
    .... 
} 

例のループカウンタ変数(行いませんこれは馬鹿だ):

int* ip = new int; 
for (*ip=0; *ip<50; ++(*ip)) { 
    .... 
} 
delete ip; 

ここでatteの問題に対処する手動&貼り付けをコピーする代わりに、ループ&カウンタを使用してループを最適化するために、mpting:

あなたがやって検討している何をすることはループ展開のマニュアル形式です。ループアンローリングは、ループに含まれるオーバーヘッドを減らすためにコンパイラが時々使用する最適化です。コンパイラは、コンパイル時にループの反復回数を知ることができる(すなわち、反復回数は、定数が他の定数に基づく計算を含んでいても定数である)場合にのみ実行できます。場合によっては、コンパイラはループを展開する価値があると判断することがありますが、完全に展開しないことがよくあります。たとえば、あなたの例では、コンパイラは、ループの50回の繰り返しから5回のループ本体の10回の反復まで、ループを展開するのがスピード上の利点であると判断することがあります。ループ変数はまだそこにありますが、ループカウンターを50回比較する代わりに、コードは比較を10回だけ実行する必要があります。これはトレードオフです。ループ本体の5つのコピーがキャッシュ内の5倍のスペースを消費するため、同じ命令の余分なコピーをロードすると、すでにキャッシュされている多くの命令がキャッシュから削除されますキャッシュと、キャッシュに残したいと思っていたかもしれません。また、ループ本体命令の4つの余分なコピーをメインメモリからロードすることは、ループがまったく展開されていない場合にキャッシュから既にロードされた命令を単に取り込むことよりもはるかに長い時間を要する。

このように、ループ本体のコピーを1つだけ使用してループロジックをそのままにしておくと、しばしばより有利です。 (つまり、ループをまったく展開しないでください)

+0

2番目のループは決して実行されません。私はあなたが 'int i = 0;'を意味したと思いますか? – Aleph

+0

@AnotherTest - あなたはコードピアレビューのためのケースを作る!ありがとう。 – phonetagger

-1

私はスピードの最大の増加は、反復変数を割り当てていないという事実でしょうが、あなたが求めたものは、条件をチェックする必要があります。本質的にあなたが持っているものは以下の通りです。

int i = 0; 
for(; i< 50; i++) 
{ 
    Do Something. 
} 

私がforループの外側に移動した理由は、ループの前に初期化された任意の変数になることができるということです。 CおよびC++の設計は多少ありません - percisely言語の一部としてrepeat(x)を持つことが完全に可能だろうが、いくつかの理由でそのような事がない

for(int i =0; i< 50; i++) 
{ 
} 
+0

なぜfor(int i = 0; i <...)? –

+0

これはまったく同じですか?ちょうど初期化をforループから外した。単にそれがループの前の任意のポイントで作成された変数かもしれないと言います。 – Nomad101

+0

変数は毎回割り当てられません。このコードはループ内で 'i'を宣言するのと同じです。 –

1

、と同じことですプロセッサーができることに従ってください。私は、「何回もループする」ことができる単一のプロセッサー(私は約10種類のプロセッサー・アーキテクチャーで作業してきました)には慣れていません。 "

何回繰り返したのかを確認するコードを書く必要があります(何回残っていますか?それを行う "ループ"というx86命令があります)。カウンタがゼロでない場合は、ループの先頭にジャンプします)。

コンパイラが反復回数が一定であるためにループを "アンロール"し、 "アンローリングが速い"と判断した場合[コンパイラはこれらの種類のものを常に決定し、コンパイラはそうすることができます。しかし、 "チェック"するコードを書く必要があります。

+0

プロセッサのことをありがとう、面白かったです。コンパイラの最適化を完全に忘れてしまった。 – Serdnad

関連する問題