tl; dr: Phiên bản cục bộ giữ N trong sổ đăng ký, phiên bản toàn cầu thì không. Khai báo hằng số với const và sẽ nhanh hơn bất kể bạn khai báo nó như thế nào.
Dưới đây là đoạn code ví dụ tôi sử dụng:
#include <iostream>
#include <math.h>
void first(){
int x=1;
int N = 10000;
for(int i = 0; i < N; ++i)
tan(tan(tan(tan(tan(tan(tan(tan(x++))))))));
std::cout << x;
}
int N=10000;
void second(){
int x=1;
for(int i = 0; i < N; ++i)
tan(tan(tan(tan(tan(tan(tan(tan(x++))))))));
std::cout << x;
}
int main(){
first();
second();
}
(tên test.cpp
).
Để xem mã trình tạo đã tạo, tôi chạy g++ -S test.cpp
.
tôi nhận được một tập tin rất lớn, nhưng với một số tìm kiếm thông minh (Tôi đã tìm kiếm cho tan), tôi thấy những gì tôi muốn:
từ first
chức năng:
Ltmp2:
movl $1, -4(%rbp)
movl $10000, -8(%rbp) ; N is here !!!
movl $0, -12(%rbp) ;initial value of i is here
jmp LBB1_2 ;goto the 'for' code logic
LBB1_1: ;the loop is this segment
movl -4(%rbp), %eax
cvtsi2sd %eax, %xmm0
movl -4(%rbp), %eax
addl $1, %eax
movl %eax, -4(%rbp)
callq _tan
callq _tan
callq _tan
callq _tan
callq _tan
callq _tan
callq _tan
movl -12(%rbp), %eax
addl $1, %eax
movl %eax, -12(%rbp)
LBB1_2:
movl -12(%rbp), %eax ;value of n kept in register
movl -8(%rbp), %ecx
cmpl %ecx, %eax ;comparing N and i here
jl LBB1_1 ;if less, then go into loop code
movl -4(%rbp), %eax
chức năng thứ hai:
Ltmp13:
movl $1, -4(%rbp) ;i
movl $0, -8(%rbp)
jmp LBB5_2
LBB5_1: ;loop is here
movl -4(%rbp), %eax
cvtsi2sd %eax, %xmm0
movl -4(%rbp), %eax
addl $1, %eax
movl %eax, -4(%rbp)
callq _tan
callq _tan
callq _tan
callq _tan
callq _tan
callq _tan
callq _tan
movl -8(%rbp), %eax
addl $1, %eax
movl %eax, -8(%rbp)
LBB5_2:
movl _N(%rip), %eax ;loading N from globals at every iteration, instead of keeping it in a register
movl -8(%rbp), %ecx
Vì vậy, từ mã trình lắp ráp, bạn có thể thấy (hoặc không), trong phiên bản cục bộ, N được giữ trong sổ đăng ký trong suốt quá trình tính toán, trong khi ở phiên bản toàn cầu, N được đọc lại từ toàn cầu tại mỗi lần lặp.
Tôi tưởng tượng lý do chính tại sao điều này xảy ra là cho những thứ như luồng, trình biên dịch không thể chắc chắn rằng N không được sửa đổi.
nếu bạn thêm một const
để việc kê khai của N (const int N=10000
), nó sẽ nhanh hơn so với phiên bản địa phương mặc dù:
movl -8(%rbp), %eax
addl $1, %eax
movl %eax, -8(%rbp)
LBB5_2:
movl -8(%rbp), %eax
cmpl $9999, %eax ;9999 used instead of 10000 for some reason I do not know
jle LBB5_1
N được thay thế bằng một hằng số.
Tôi cho rằng trình biên dịch có thể nghi ngờ rằng 'x' được sửa đổi bên trong hàm' tan' ngăn cản nhiều tối ưu hóa. Tôi không chắc chắn rằng điều này xảy ra ở đây mặc dù. – Pubby
@Pubby Sự khác biệt duy nhất là giảm tốc độ N mặc dù? –
tốt, nếu 'x' là cục bộ thì rõ ràng là không thể sửa đổi bên trong' tan'. Vì vậy, khai báo không thành vấn đề. – Pubby