2011-08-07 23 views
17

Test:Tại sao std :: sin() và std :: cos() chậm hơn sin() và cos()? đang

#include <cmath> 
#include <cstdio> 

const int N = 4096; 
const float PI = 3.1415926535897932384626; 

float cosine[N][N]; 
float sine[N][N]; 

int main() { 
    printf("a\n"); 
    for (int i = 0; i < N; i++) { 
     for (int j = 0; j < N; j++) { 
      cosine[i][j] = cos(i*j*2*PI/N); 
      sine[i][j] = sin(-i*j*2*PI/N); 
     } 
    } 
    printf("b\n"); 
} 

Đây là thời điểm:

$ g++ main.cc -o main 
$ time ./main 
a 
b 

real 0m1.406s 
user 0m1.370s 
sys  0m0.030s 

Sau khi thêm using namespace std;, thời gian là:

$ g++ main.cc -o main 
$ time ./main 
a 
b 

real 0m8.743s 
user 0m8.680s 
sys  0m0.030s 

Compiler:

$ g++ --version 
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 

hội:

Dump of assembler code for function [email protected]:          
0x0000000000400500 <+0>:  jmpq *0x200b12(%rip)  # 0x601018 <_GLOBAL_OFFSET_TABLE_+48> 
0x0000000000400506 <+6>:  pushq $0x3          
0x000000000040050b <+11>: jmpq 0x4004c0         
End of assembler dump. 

Dump of assembler code for function std::sin(float):        
0x0000000000400702 <+0>:  push %rbp          
0x0000000000400703 <+1>:  mov %rsp,%rbp         
0x0000000000400706 <+4>:  sub $0x10,%rsp        
0x000000000040070a <+8>:  movss %xmm0,-0x4(%rbp)       
0x000000000040070f <+13>: movss -0x4(%rbp),%xmm0       
0x0000000000400714 <+18>: callq 0x400500 <[email protected]>      
0x0000000000400719 <+23>: leaveq           
0x000000000040071a <+24>: retq            
End of assembler dump. 

Dump of assembler code for function [email protected]:         
0x0000000000400500 <+0>:  jmpq *0x200b12(%rip)  # 0x601018 <_GLOBAL_OFFSET_TABLE_+48> 
0x0000000000400506 <+6>:  pushq $0x3          
0x000000000040050b <+11>: jmpq 0x4004c0         
End of assembler dump. 
+11

@Nawaz: Có thể. Đó là một chi tiết thực hiện cho dù '' cung cấp 'double sin (double)' và 'double cos (double)' trong không gian tên chung. Ditto cho '' và 'printf'. –

+0

@Nawaz Nó biên dịch. Đó là mã hóa thực sự của tôi. – rynlbrwn

+0

Cách dễ nhất để trả lời các vấn đề như thế này là bằng cách so sánh đầu ra của trình biên dịch. –

Trả lời

19

Bạn đang sử dụng quá tải khác nhau:

Hãy thử

 double angle = i*j*2*PI/N; 
     cosine[i][j] = cos(angle); 
     sine[i][j] = sin(angle); 

nó nên thực hiện cùng với hoặc không có using namespace std;

+0

Mã của bạn hoạt động, nhưng nó chạy nhanh có hoặc không có thay đổi không gian tên. Tại sao mã tôi cung cấp chạy chậm hơn nhiều? – rynlbrwn

+11

@Ryan: Bởi vì mã của tôi luôn gọi 'double sin (double) '. Mã ban đầu của bạn gọi là 'double sin (double)' từ phạm vi toàn cục, hoặc 'float sin (float)' từ 'namespace std'. FPU hiện đại được tối ưu hóa cho các hoạt động trên đôi. –

+0

Đã thêm một số hội đồng, kết luận của bạn vẫn còn giữ? (Tôi không có ninja lắp ráp) – rynlbrwn

3

tôi đoán sự sự khác biệt là có quá tải cho std :: sin() cho float và fo r đôi, trong khi sin() chỉ mất gấp đôi. Bên trong std :: sin() cho float, có thể có một chuyển đổi để tăng gấp đôi, sau đó một cuộc gọi đến std :: sin() để tăng gấp đôi, và sau đó chuyển đổi kết quả trở lại float, làm cho nó chậm hơn.

+0

Chuyển đổi giữa 'float' và' double' không tính đến nó. Tôi chạy một số thử nghiệm ngày hôm nay với g + + và thấy rằng khi sử dụng '-O2' mã' float' chậm hơn nhiều.Tuy nhiên, khi tôi thử nghiệm với các chuyển đổi thủ công, như thế này: '(float) sin ((double) input)' Tôi thấy rằng mã 'float' được tối ưu hóa chạy _faster_ hơn mã' double' được tối ưu hóa, mặc dù tôi đã buộc ' float' để sử dụng hàm 'double'' sin'. –

+0

@KyleA: Đó là năm 2011. Bây giờ là năm 2017. Mã thời gian chạy có thể đã thay đổi. –

1

Sử dụng -S gắn cờ trong dòng lệnh trình biên dịch và kiểm tra sự khác biệt giữa đầu ra bộ kết hợp. Có thể using namespace std; cung cấp nhiều nội dung không sử dụng trong tệp thi hành.

+0

Đó là lý do tại sao tôi có các câu lệnh in, để nếu bạn chạy mã, bạn có thể thấy rằng phần lớn thời gian được sử dụng trong vòng lặp chứ không phải khởi tạo. – rynlbrwn

Các vấn đề liên quan