奇怪的基准测试结果
Strange benchmark results
我写了以下基准:
#include <iostream> // cout
#include <math.h> // pow
#include <chrono> // high_resolution_clock
using namespace std;
using namespace std::chrono;
int64_t calculate(int);
int main()
{
high_resolution_clock::time_point t1, t2;
// Test 1
t1 = high_resolution_clock::now();
calculate(200);
t2 = high_resolution_clock::now();
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
// Test 2
t1 = high_resolution_clock::now();
calculate(200000);
t2 = high_resolution_clock::now();
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
}
int64_t calculate(const int max_exponent)
{
int64_t num = 0;
for(int i = 0; i < max_exponent; i++)
{
num += pow(2, i);
}
return num;
}
当 运行 在 Odroid XU3 上进行此基准测试时,会产生以下输出(8 次运行):
RUNTIME TEST 1 = 1250 nano seconds
RUNTIME TEST 2 = 1041 nano seconds
RUNTIME TEST 1 = 1292 nano seconds
RUNTIME TEST 2 = 1042 nano seconds
RUNTIME TEST 1 = 1250 nano seconds
RUNTIME TEST 2 = 1083 nano seconds
RUNTIME TEST 1 = 1292 nano seconds
RUNTIME TEST 2 = 1083 nano seconds
RUNTIME TEST 1 = 1209 nano seconds
RUNTIME TEST 2 = 1084 nano seconds
RUNTIME TEST 1 = 1166 nano seconds
RUNTIME TEST 2 = 1083 nano seconds
RUNTIME TEST 1 = 1292 nano seconds
RUNTIME TEST 2 = 1042 nano seconds
RUNTIME TEST 1 = 1166 nano seconds
RUNTIME TEST 2 = 1250 nano seconds
RUNTIME TEST 1 = 1250 nano seconds
RUNTIME TEST 2 = 1250 nano seconds
第二个指数是第一个指数的 1000 倍。为什么有时第二次通话完成得更快?
我使用 GCC (4.8) 作为带有 -Ofast
标志的编译器。
更新: 我可以在我的 i7 4770k 上重现类似的行为。
这可能是在您的 CPU 缓存的帮助下发生的
或者,很可能是编译器的优化。尝试使用 -O0 禁用优化并比较结果。
我在有和没有“-O0”的机器上重复了它,得到了完全不同的结果。
简短的回答是 "dead code elimination"。编译器发现你从不使用调用函数的结果(而且函数没有副作用),所以它只是消除了调用函数。
打印出函数的结果,情况发生了一些变化。例如:
Ignore: -9223372036854775808 RUNTIME = 0 nano seconds
Ignore: -9223372036854775808 RUNTIME = 23001300 nano seconds
修改后的代码,以防万一:
#include <iostream> // cout
#include <math.h> // pow
#include <chrono> // high_resolution_clock
using namespace std;
using namespace std::chrono;
int64_t calculate(int);
int main() {
high_resolution_clock::time_point t1, t2;
// Test 1
t1 = high_resolution_clock::now();
auto a = calculate(200);
t2 = high_resolution_clock::now();
std::cout << "Ignore: " << a << "\t";
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
// Test 2
t1 = high_resolution_clock::now();
auto b = calculate(200000);
t2 = high_resolution_clock::now();
std::cout << "Ignore: " << b << "\t";
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
}
int64_t calculate(const int max_exponent) {
int64_t num = 0;
for (int i = 0; i < max_exponent; i++) {
num += pow(2, i);
}
return num;
}
从那里你有一些次要的细节,你正在溢出 int64_t
的范围(多次)给出未定义的行为 - 但至少有理由希望打印出的时间反映执行指定计算的时间。
我写了以下基准:
#include <iostream> // cout
#include <math.h> // pow
#include <chrono> // high_resolution_clock
using namespace std;
using namespace std::chrono;
int64_t calculate(int);
int main()
{
high_resolution_clock::time_point t1, t2;
// Test 1
t1 = high_resolution_clock::now();
calculate(200);
t2 = high_resolution_clock::now();
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
// Test 2
t1 = high_resolution_clock::now();
calculate(200000);
t2 = high_resolution_clock::now();
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
}
int64_t calculate(const int max_exponent)
{
int64_t num = 0;
for(int i = 0; i < max_exponent; i++)
{
num += pow(2, i);
}
return num;
}
当 运行 在 Odroid XU3 上进行此基准测试时,会产生以下输出(8 次运行):
RUNTIME TEST 1 = 1250 nano seconds
RUNTIME TEST 2 = 1041 nano seconds
RUNTIME TEST 1 = 1292 nano seconds
RUNTIME TEST 2 = 1042 nano seconds
RUNTIME TEST 1 = 1250 nano seconds
RUNTIME TEST 2 = 1083 nano seconds
RUNTIME TEST 1 = 1292 nano seconds
RUNTIME TEST 2 = 1083 nano seconds
RUNTIME TEST 1 = 1209 nano seconds
RUNTIME TEST 2 = 1084 nano seconds
RUNTIME TEST 1 = 1166 nano seconds
RUNTIME TEST 2 = 1083 nano seconds
RUNTIME TEST 1 = 1292 nano seconds
RUNTIME TEST 2 = 1042 nano seconds
RUNTIME TEST 1 = 1166 nano seconds
RUNTIME TEST 2 = 1250 nano seconds
RUNTIME TEST 1 = 1250 nano seconds
RUNTIME TEST 2 = 1250 nano seconds
第二个指数是第一个指数的 1000 倍。为什么有时第二次通话完成得更快?
我使用 GCC (4.8) 作为带有 -Ofast
标志的编译器。
更新: 我可以在我的 i7 4770k 上重现类似的行为。
这可能是在您的 CPU 缓存的帮助下发生的 或者,很可能是编译器的优化。尝试使用 -O0 禁用优化并比较结果。 我在有和没有“-O0”的机器上重复了它,得到了完全不同的结果。
简短的回答是 "dead code elimination"。编译器发现你从不使用调用函数的结果(而且函数没有副作用),所以它只是消除了调用函数。
打印出函数的结果,情况发生了一些变化。例如:
Ignore: -9223372036854775808 RUNTIME = 0 nano seconds
Ignore: -9223372036854775808 RUNTIME = 23001300 nano seconds
修改后的代码,以防万一:
#include <iostream> // cout
#include <math.h> // pow
#include <chrono> // high_resolution_clock
using namespace std;
using namespace std::chrono;
int64_t calculate(int);
int main() {
high_resolution_clock::time_point t1, t2;
// Test 1
t1 = high_resolution_clock::now();
auto a = calculate(200);
t2 = high_resolution_clock::now();
std::cout << "Ignore: " << a << "\t";
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
// Test 2
t1 = high_resolution_clock::now();
auto b = calculate(200000);
t2 = high_resolution_clock::now();
std::cout << "Ignore: " << b << "\t";
cout << "RUNTIME = " << duration_cast<nanoseconds>(t2 - t1).count() << " nano seconds" << endl;
}
int64_t calculate(const int max_exponent) {
int64_t num = 0;
for (int i = 0; i < max_exponent; i++) {
num += pow(2, i);
}
return num;
}
从那里你有一些次要的细节,你正在溢出 int64_t
的范围(多次)给出未定义的行为 - 但至少有理由希望打印出的时间反映执行指定计算的时间。