1

コンパイル時に for ループを何回反復する必要があるかを知ることには利点がありますか?

たとえば、状況によっては、コンパイラは次の条件でより高速に実行される実行可能ファイルを生成できます。

#define ITERATIONS 10
int foo()
{
    for (int i=0; i < ITERATIONS; i++){
        do_something();
    }
}

これよりも:

int foo(int iterations)
{
    for (int i=0; i < iterations; i++){
        do_something();
    }
}

これが普遍的なケースではない場合、それらの状況はどのようなものですか?

私の懸念は OpenCL の特定のケースにあるため、これが C と異なるかどうかも知りたい.

4

5 に答える 5

7

GCC を使用してかなり現実的な状況でテストしました。コンパイル時にループの数がわかると、次のようになります。

.L2:
    call    do_something
    subl    $1, %ebx
    jne .L2

そうでない場合は、次のようになります。

.L6:
    call    do_something
    addl    $1, %ebx
    cmpl    %ebp, %ebx
    jne .L6

そのため、カウント アップ ループではなくカウント ダウン ツー ゼロ ループに変更することで、固定反復回数をわずかに最適化することができました。少なくとも、これは少し少ないコード キャッシュを使用します。

最適化レベルを高くすると、外部関数を 10 回呼び出すループが完全に展開されます。おそらく、それがより良いと思わない限り、それはしません。そして、反復回数が不明な場合、それは確かにできません。

簡単な答え: 反復回数を固定すると、コンパイラにより多くのオプションが与えられます。これにより、少なくとも場合によっては、コードがわずかに改善されるはずです。

于 2012-10-18T12:15:12.040 に答える
4

確かに、それはコンパイラに依存します。しかし、事実上、ループの展開が可能になります。これはIntelの例AMDの例です。

NVIDIAでは、カーネルに次のものが必要です#pragma OPENCL EXTENSION cl_nv_pragma_unroll : enable

したがって、コンパイル時に次のようなフラグを使用できます。-DITERATIONS=10

于 2012-10-18T12:21:37.560 に答える
3

初期化する必要がありますi

for (int i; i < ITERATIONS; i++){

は未定義の動作であり、コンパイラがループを完全にスキップできるようにします;)

それとは別に、コンパイル時に反復回数がわかっている場合、たとえば、コンパイラーはループを完全に展開できます。これにより、大きな違いが生じる可能性があります(ループ本体が安価な場合)。

于 2012-10-18T12:07:41.353 に答える
1

gcc-4.5.3の場合、do_something() {printf("hello world")}

  • 最適化なしまたはat-O2の場合、コンパイラはどちらのループも展開しません。
  • -O4、既知の反復回数の場合のみ、コンパイラはループを展開してインライン化しdo_something()ます。

foo:
...
.L4:
        addl    $1, %ebx
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
        cmpl    %ebx, %esi
        jg      .L4

main:
...
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
...
于 2012-10-18T12:21:45.457 に答える
1

これは、使用しているコンパイラと最適化の設定に大きく依存します。ほとんどの場合、ループの量を知ることで、コンパイラはループをアンロールし、分岐とパラメーター i を取り除くことができます。

ただし、これは完全にコンパイラに依存するため、当てにしないでください。ただし、最新のコンパイラを使用している場合は、速度が向上する可能性が高くなります。

編集:

明らかな初期化されていない i を読みましたが、おそらくあなたもそうしました...

于 2012-10-18T12:09:07.250 に答える