この回答は、Murilo Vasconcelos への回答です。
フォローするにはhttp://gcc.godbolt.org/を使用してください。
#include <stdio.h>
#include <ctime>
#include <cstdlib>
int main() {
int i;
srand(time(NULL));
for(i=0; i< 10; i++){
printf(" %d ", rand() % 300);
if(i < 10 - 1){
printf("|");
}
}
}
g++-4.8 を使用して次のアセンブリを生成します。
.LC0:
.string " %d "
main:
pushq %rbp
xorl %edi, %edi
movl $458129845, %ebp
pushq %rbx
xorl %ebx, %ebx
subq $8, %rsp
call time
movl %eax, %edi
call srand
call rand
movl $458129845, %edx
movl $.LC0, %edi
movl %eax, %esi
imull %edx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
.L2:
movl $124, %edi
addl $1, %ebx
call putchar
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebp
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
cmpl $9, %ebx
jne .L2
addq $8, %rsp
xorl %eax, %eax
popq %rbx
popq %rbp
ret
一方、このコード:
#include <stdio.h>
#include <ctime>
#include <cstdlib>
int main() {
int i;
srand(time(NULL));
for (i = 0; i < 9; i++) {
printf(" %d |", rand() % 300);
}
printf(" %d ", rand() % 300);
}
このアセンブリを生成します:
.LC0:
.string " %d |"
.LC1:
.string " %d "
main:
pushq %rbx
xorl %edi, %edi
movl $458129845, %ebx
call time
movl %eax, %edi
call srand
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $5, %edx
sarl $31, %eax
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC0, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
call rand
movl $.LC1, %edi
movl %eax, %esi
imull %ebx
movl %esi, %eax
sarl $31, %eax
sarl $5, %edx
subl %eax, %edx
xorl %eax, %eax
imull $300, %edx, %edx
subl %edx, %esi
call printf
xorl %eax, %eax
popq %rbx
ret
つまり、ループを変更することで、コンパイラはループをアンロールできるようになりました。これは、変更なしでは得られない大幅なパフォーマンスの向上になるはずです。ですから、人々にうんちをさせないでください。アセンブリがどうなるかを自分で確認してください。手作業による最適化がすべて時間の無駄というわけではありません。そしてもちろん、テストテストテスト。
しかし、もちろん、時期尚早に最適化するべきではありません。プロファイラーに従って、ホット スポットが何であるか、最適化が必要な場所を教えてもらう必要があります。
より良いアルゴリズムを最初に。
次に、より良いコード。
次に、より良いアセンブリ。