tan funcion dev asin c++ performance cmath sin cos

funcion - sin c++



¿Por qué es std:: sin() y std:: cos() más lento que sin() y cos()? (4)

Creo que la diferencia es que hay sobrecargas para std :: sin () para float y para double, mientras que sin () solo toma el doble. Dentro de std :: sin () para flotadores, puede haber una conversión para doblar, luego una llamada a std :: sin () para dobles, y luego una conversión del resultado a flotar, haciéndolo más lento.

Código de prueba:

#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í está el tiempo:

$ g++ main.cc -o main $ time ./main a b real 0m1.406s user 0m1.370s sys 0m0.030s

Después de agregar using namespace std; , la hora 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 sin@plt: 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 <sinf@plt> 0x0000000000400719 <+23>: leaveq 0x000000000040071a <+24>: retq End of assembler dump. Dump of assembler code for function sinf@plt: 0x0000000000400500 <+0>: jmpq *0x200b12(%rip) # 0x601018 <_GLOBAL_OFFSET_TABLE_+48> 0x0000000000400506 <+6>: pushq $0x3 0x000000000040050b <+11>: jmpq 0x4004c0 End of assembler dump.


Estás usando una sobrecarga diferente:

Tratar

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

debe realizar lo mismo con o sin using namespace std;


Hice algunas mediciones utilizando Clang con optimización de -O3 , ejecutándose en un Intel Core i7 . Encontre eso:

  • std::sin en float tiene el mismo costo que sinf
  • std::sin en double tiene el mismo costo que sin
  • Las funciones sin en double son 2.5x más lentas que en float (nuevamente, ejecutándose en un Intel Core i7 ).

Aquí está el código completo para reproducirlo:

#include <chrono> #include <cmath> #include <iostream> template<typename Clock> struct Timer { using rep = typename Clock::rep; using time_point = typename Clock::time_point; using resolution = typename Clock::duration; Timer(rep& duration) : duration(&duration) { startTime = Clock::now(); } ~Timer() { using namespace std::chrono; *duration = duration_cast<resolution>(Clock::now() - startTime).count(); } private: time_point startTime; rep* duration; }; template<typename T, typename F> void testSin(F sin_func) { using namespace std; using namespace std::chrono; high_resolution_clock::rep duration = 0; T sum {}; { Timer<high_resolution_clock> t(duration); for(int i=0; i<100000000; ++i) { sum += sin_func(static_cast<T>(i)); } } cout << duration << endl; cout << " " << sum << endl; } int main() { testSin<float> ([] (float v) { return std::sin(v); }); testSin<float> ([] (float v) { return sinf(v); }); testSin<double>([] (double v) { return std::sin(v); }); testSin<double>([] (double v) { return sin(v); }); return 0; }

Me interesaría si la gente pudiera informar, en los comentarios sobre los resultados de sus arquitecturas, especialmente con respecto al tiempo float frente al double .


Use el indicador -S en la línea de comando del compilador y verifique la diferencia entre la salida del ensamblador. Tal vez using namespace std; da un montón de cosas no utilizadas en el archivo ejecutable.