7
#include <stdio.h>
int main() {
        int i;
        for(i=0;i<10000;i++){
            printf("%d",i);
    }
}

gcc を使用して、このコードでループの展開を行いたいのですが、フラグも使用します。

gcc -O2 -funroll-all-loops --save-temps unroll.c

私が取得しているアセンブルされたコードには、10000回の反復のループが含まれています

_main:
Leh_func_begin1:
        pushq   %rbp
Ltmp0:
movq    %rsp, %rbp
Ltmp1:
pushq   %r14
pushq   %rbx
Ltmp2:
xorl    %ebx, %ebx
leaq    L_.str(%rip), %r14
.align  4, 0x90
LBB1_1:
xorb    %al, %al
movq    %r14, %rdi
movl    %ebx, %esi
callq   _printf
incl    %ebx
cmpl    $10000, %ebx
jne LBB1_1
popq    %rbx
popq    %r14
popq    %rbp
ret
Leh_func_end1:

gcc でループ展開を正しく実装する方法を教えてください。

4

3 に答える 3

7

ループ展開は、このコードには何のメリットもありません。関数呼び出しprintf()自体のオーバーヘッドが、各反復で行われる作業を支配するからです。コンパイラはこれを認識している可能性があり、コードを最適化するように求められているため、実行時のパフォーマンスがあまり向上しないのにアンロールによってコード サイズが大きくなると判断し、命令キャッシュ ミスが発生するリスクが高すぎると判断する場合があります。アンローリングを実行します。

このループを高速化するために必要なタイプのアンロールでは、printf()それ自体への呼び出しの数を減らす必要があります。それができる最適化コンパイラを私は知りません。

呼び出し回数を減らすためにループを展開する例として、次のprintf()コードを検討してください。

void print_loop_unrolled (int n) {
    int i = -8;
    if (n % 8) {
        printf("%.*s", n % 8, "01234567");
        i += n % 8;
    }
    while ((i += 8) < n) {
        printf("%d%d%d%d%d%d%d%d",i,i+1,i+2,i+3,i+4,i+5,i+6,i+7);
    }
}
于 2013-09-30T22:29:36.373 に答える
6

gcc最大ループ展開パラメーターがあります。

-O3 -funroll-loopsパラメータmax-unroll-timesmax-unrolled-insnsおよびを使用して操作する必要がありますmax-average-unrolled-insns

例:

-O3 -funroll-loops --param max-unroll-times=200
于 2013-09-30T22:11:57.263 に答える