최적화를 한다면 일반적으로 루프를 풀어봤자 큰 차이는 없습니다. 반복횟수가 아주 많은 루프는 풀어서도 안되구요. 오히려 펜티엄2 이상이라면 루프를 돌리는게 풀어서 처리하는 것보다 더 빠를 수 있습니다. history에 기록이 남고 BTB에 들어가기 때문이죠.
더군다나 CPU는 backward conditional jump의 목적지를 기본 예측대상으로 삼기때문에 루프로 인한 점프가 있다 해서 파이프라인이 리셋되거나 하진 않습니다.
단 실행구조상 직렬배치된 다수의 서로 다른 루프 내에 점프 가능성이 낮은 if-continue문들이 여럿 있다면 얘기가 달라지겠지만요.. 하지만 이런 경우엔 루프를 컴파일러가 풀어써도 forward conditional jump 코드를 생성시켜 예측을 실패하게 만들기때문에 효과가 없습니다... 직접 풀어서 써야죠.
[code:1]urmajest@anecdote urmajest $ c
urmajest@anecdote urmajest $ cat test.c #include<stdio.h> int main() { int i; for (i = 0; i < 16; ++i) ++i; printf("%d\n", i); return 1; } urmajest@anecdote urmajest $ gcc -O3 -S test.c urmajest@anecdote urmajest $ cat test.s .file "test.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "%d\n" .text .p2align 4,,15 .globl main .type main, @function main: pushl %ebp xorl %eax, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp .p2align 4,,15 .L6: addl $2, %eax cmpl $15, %eax jle .L6 movl $.LC0, (%esp) movl $16, %edx movl %edx, 4(%esp) call printf movl %ebp, %esp movl $1, %eax popl %ebp ret .size main, .-main .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.3.5 (Gentoo Linux 3.3.5-r1, ssp-3.3.2-3, pie-8.7.7.1)" urmajest@anecdote urmajest $ gcc -O3 -funroll-loops -S test.c urmajest@anecdote urmajest $ cat test.s .file "test.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "%d\n" .text .p2align 4,,15 .globl main .type main, @function main: pushl %ebp movl $16, %edx movl %esp, %ebp subl $8, %esp andl $-16, %esp movl %edx, 4(%esp) movl $.LC0, (%esp) call printf movl %ebp, %esp movl $1, %eax popl %ebp ret .size main, .-main .section .note.GNU-stack,"",@progbits .ident "GCC: (GNU) 3.3.5 (Gentoo Linux 3.3.5-r1, ssp-3.3.2-3, pie-8.7.7.1)"loop이 사라졌네요 ^^
P.S. 글 올릴 때는 어셈블리 코드를 자세히 안 봤는데, 그리 좋은 예제는 아닌 것 같네요. strength reduction이 대박되는 예제를 실행해보면 시간 차이가 나지 않을까 싶네요.
loop unrolling은 반복적인 코드로는 영향이 없습니다.
최적화를 한다면 일반적으로 루프를 풀어봤자 큰 차이는 없습니다. 반복횟수가 아주 많은 루프는 풀어서도 안되구요. 오히려 펜티엄2 이상이라면 루프를 돌리는게 풀어서 처리하는 것보다 더 빠를 수 있습니다. history에 기록이 남고 BTB에 들어가기 때문이죠.
더군다나 CPU는 backward conditional jump의 목적지를 기본 예측대상으로 삼기때문에 루프로 인한 점프가 있다 해서 파이프라인이 리셋되거나 하진 않습니다.
단 실행구조상 직렬배치된 다수의 서로 다른 루프 내에 점프 가능성이 낮은 if-continue문들이 여럿 있다면 얘기가 달라지겠지만요.. 하지만 이런 경우엔 루프를 컴파일러가 풀어써도 forward conditional jump 코드를 생성시켜 예측을 실패하게 만들기때문에 효과가 없습니다... 직접 풀어서 써야죠.
쩝.. 얘기가 복잡해지는 듯...
IA-32 Intel
님ㅎ 즐~
댓글 달기