2011-08-07 11 views
17

prueba:¿Por qué std :: sin() y std :: cos() son más lentos que sin() y cos()? código

#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"); 
} 

Aquí es el momento:

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

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

Después de añadir using namespace std;, el tiempo es:

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

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

Compilador:

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

Montaje:

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: Podría. Es un detalle de implementación si '' proporciona 'double sin (double)' y 'double cos (double)' en el espacio de nombres global. Ídem para '' y 'printf'. –

+0

@Nawaz Compila. Es mi codificación real. – rynlbrwn

+0

La forma más fácil de responder a problemas como este es mediante la comparación de la salida de ensamblaje del compilador. –

Respuesta

19

Estás usando una sobrecarga diferente:

Trate

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

que debe realizar la misma con o sin using namespace std;

+0

Su código funciona, pero se ejecuta rápidamente con o sin el cambio de espacio de nombres. ¿Por qué el código que proporcioné se ejecuta mucho más lento? – rynlbrwn

+11

@Ryan: Porque mi código siempre llama a 'double sen (double) '. Su código original llama ya sea 'double sin (double)' desde el alcance global, o 'float sin (float)' desde 'namespace std'. Las FPU modernas están optimizadas para operaciones en dobles. –

+0

Agregó un ensamblaje, ¿su conclusión aún se mantiene? (No soy un ninja de ensamblaje) – rynlbrwn

3

I adivinar el la diferencia es que hay sobrecargas para std :: sin() para float y fo r doble, mientras que sin() solo toma el doble. Dentro de std :: sin() para flotantes, puede haber una conversión a doble, luego una llamada a std :: sin() para dobles, y luego una conversión del resultado de nuevo a flotante, haciéndolo más lento.

+0

Las conversiones entre 'float' y' double' no lo tienen en cuenta. Realicé algunas pruebas hoy con g ++ y descubrí que al usar '-O2', el código' flotar 'era mucho más lento.Sin embargo, cuando probé con conversiones manuales, así: '(float) sin ((double) input)' Encontré que el código optimizado 'flotar' corría _faster_ que el código' doble' optimizado, a pesar de que estaba forzando ' Código de flotación para usar la función '' doble' 'sin' –

+0

@KyleA: Eso fue en 2011. Ahora es 2017. El código de tiempo de ejecución puede haber cambiado. –

1

Utilice la marca -S en la línea de comandos del compilador y compruebe la diferencia entre la salida del ensamblador. Tal vez using namespace std; da un montón de cosas sin usar en el archivo ejecutable.

+0

Es por eso que tenía las instrucciones de impresión, de modo que si ejecutaba el código, podría ver que la mayor parte del tiempo se gasta en el ciclo, no en la inicialización. – rynlbrwn

Cuestiones relacionadas