2015-01-05 7 views
5

私が知っているループをn回実行する必要がある場合は、毎回比較せずにwhile(またはfor)ループを書く方法がありますか?Cで比較n回なしのループ

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

へ:

operation(); 
operation(); 
operation(); 
operation(); 
operation(); 

P.S.マクロターンを作るための方法があるない場合これは私が今までに出てきた最速のループです。

int i = 5; 
while(i-- >= 0) { 
    operation(); 
} 
+4

これは何もする必要はありません。より効果的であれば、コンパイラはすでにループを展開しています。 – ThiefMaster

+0

なぜそれをしたいですか?命令キャッシュのスペースが増え、命令のデコードが多くなり、基本的に悪化します。それが良ければ、コンパイラはそれをあなたのために変換しないでしょうか? (それが迷惑でない限り、なぜあなたはそれを使用していますか?) –

答えて

7

十分にスマートなコンパイラがこれを行います。より具体的には、最適化コンパイラはループアンローリングを理解します。非常に基本的な最適化です。特に、コンパイル時に反復回数がわかっている例のような場合には最適です。

簡潔に言えば、コンパイラの最適化をオンにして、心配する必要はありません。

0

両方のループが比較を行います。..

とにかくコンパイラが一定の反復を特定し、ループを展開する必要があります。

gccと最適化フラグ(-O)で確認し、その後で生成されたコードを調べることができます。

さらに重要: 重要な理由がない限り最適化しないでください。

5

ソースコードに書き込む命令の数は、コンパイラが生成するマシン命令の数に厳密には関係しません。

ほとんどのコンパイラは賢くあり、2番目の例のようなコードを生成することができます彼らはループが常に5回反復することを検知するため、自動的に

operation(); 
operation(); 
operation(); 
operation(); 
operation(); 

。また

あなたがプロファイリング指向の最適化を行うと、コンパイラはループが、それは次のようにしても、コードと反復の一般的な数のためにそれをアンロールも小さなボディと非常に高い繰返し回数があることを認識した場合:

while (count >= 5) { 
    operation(); 
    operation(); 
    operation(); 
    operation(); 
    operation(); 
    count -= 5; 
} 
while (count > 0) { 
    operation(); 
    count--; 
} 

これは、ナイーブバージョンと比較して、テストの約5分の1を大きなcountにします。

これが価値があるかどうかは、プロファイリングだけが知ることができるものです。

あなたはコードが少なくとも一度実行する必要があることを確かに知っていればあなたができることの一つは

do { 
    operation(); 
} while (--count); 

代わりの

while (count--) { 
    operation(); 
} 

count==0がやや迷惑である可能性を書くことですほとんどのコンパイラによって生成されたコードでは、余分なJMPフォワードを必要とするため、CPUのために:

jmp test 
loop: 
    ...operation... 
test: 
    ...do the test... 
    jne loop 
Cコードがコンパイルされたら

代わりdo { ... } whileバージョンのマシンコードはながらforループは、機械語で比較文に変換され、

loop: 
    ... opertion ... 
    ... do the test... 
    jne loop 
+0

最後のループをアンロールするには、次のようにします: 'switch(count){case 4:operation(); ケース3:operation(); ケース2:operation(); ケース1:operation(); } ' – Marian

0

単純であるので、いくつかの種類を回避する方法はありませんfor/whileループとの比較比較を使用しない一連のgotoと算術文を作成することもできますが、結果はおそらく効率が悪くなります。 radare2やgdbを使ってこれらのループを機械語にコンパイルする方法を調べて、そこでの改善方法を見てください。テンプレートで

0

、あなたのようなもので(数にコンパイル時に知られている)ループをアンロールことがあります。

namespace detail 
{ 

    template <std::size_t ... Is> 
    void do_operation(std::index_sequence<Is...>) 
    { 
     std::initializer_list<std::size_t>{(static_cast<void>(operation()), Is)...}; 
    } 

} 

template <std::size_t N> 
void do_operation() 
{ 
    detail::do_operation(std::make_index_sequence<N>()); 
} 

Live demo

コンパイラは、すでに通常の最適化の並べ替えを行うことができますループ。