Tôi đang cố gắng để tính toán thời gian cần để tính toán sqrt bằng mã C đơn giản sau đây, trong đó readTSC() là một hàm đọc bộ đếm chu trình của CPU.Tại sao trình biên dịch tạo thêm sqrts trong mã assembly được biên dịch
double sum = 0.0;
int i;
tm = readTSC();
for (i = 0; i < n; i++)
sum += sqrt((double) i);
tm = readTSC() - tm;
printf("%lld clocks in total\n",tm);
printf("%15.6e\n",sum);
Tuy nhiên, như tôi đã in ra mã assembly bằng
gcc -S timing.c -o timing.s
trên một máy Intel, kết quả (hình dưới đây) là đáng ngạc nhiên?
Tại sao có hai sqrts trong mã lắp ráp bằng một mã sử dụng lệnh sqrtsd
và lệnh còn lại bằng cách sử dụng lệnh gọi hàm? Có liên quan đến việc bỏ vòng lặp và cố thực thi hai sqrts trong một lần lặp không?
Và làm thế nào để hiểu được dòng
ucomisd %xmm0, %xmm0
Tại sao nó so sánh %xmm0
cho chính nó?
//----------------start of for loop----------------
call readTSC
movq %rax, -32(%rbp)
movl $0, -4(%rbp)
jmp .L4
.L6:
cvtsi2sd -4(%rbp), %xmm1
// 1. use sqrtsd instruction
sqrtsd %xmm1, %xmm0
ucomisd %xmm0, %xmm0
jp .L8
je .L5
.L8:
movapd %xmm1, %xmm0
// 2. use C funciton call
call sqrt
.L5:
movsd -16(%rbp), %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -16(%rbp)
addl $1, -4(%rbp)
.L4:
movl -4(%rbp), %eax
cmpl -36(%rbp), %eax
jl .L6
//----------------end of for loop----------------
call readTSC
Đó là mã chưa được tối ưu hóa. [Real code] (http://goo.gl/CewylI) đưa ra các nhánh đúng cách (không có nhánh nào trong trường hợp không phải là NaN), và loại bỏ 'je' vì nó sẽ luôn đúng sau một' ucomisd '. –