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
enfloat
tiene el mismo costo quesinf
-
std::sin
endouble
tiene el mismo costo quesin
- Las funciones sin en
double
son 2.5x más lentas que enfloat
(nuevamente, ejecutándose en unIntel 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.