测试代码:
#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");
}
现在是时候了:
$ g++ main.cc -o main
$ time ./main
a
b
real 0m1.406s
user 0m1.370s
sys 0m0.030s
添加using namespace std;
后,时间为:
$ g++ main.cc -o main
$ time ./main
a
b
real 0m8.743s
user 0m8.680s
sys 0m0.030s
编译器:
$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
大会:
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.
答案 0 :(得分:21)
你正在使用不同的重载:
尝试
double angle = i*j*2*PI/N;
cosine[i][j] = cos(angle);
sine[i][j] = sin(angle);
无论是否有using namespace std;
答案 1 :(得分:5)
我 猜测 不同之处在于,对于float和double,std :: sin()存在重载,而sin()只需要加倍。在浮点数的std :: sin()里面,可能有一个转换为double,然后调用std :: sin()为double,然后将结果转换回float,使其变慢。
答案 2 :(得分:2)
在编译器命令行中使用-S标志并检查汇编器输出之间的差异。也许using namespace std;
在可执行文件中提供了大量未使用的东西。
答案 3 :(得分:1)
我使用-O3
优化并在Intel Core i7
上运行的clang进行了一些测量。我发现:
std::sin
上的float
与sinf
的费用相同std::sin
上的double
与sin
的费用相同double
上的sin函数比float
上的sin函数慢2.5倍(再次在Intel Core i7
上运行)。以下是完整的代码:
#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;
}
如果人们可以在有关其架构结果的评论中进行报告,尤其是在float
与double
时间方面,我会很感兴趣。