c++ - 奇怪的基准测试结果

标签 c++ gcc benchmarking

我写了以下基准:

#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 上重现类似的行为。

最佳答案

简短的回答是“死代码消除”。编译器发现您从不使用调用该函数的结果(并且该函数没有副作用),因此它只是消除了对函数的调用。

打印出函数的结果,事情发生了一些变化。例如:

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 的范围(多次)给出未定义的行为 - 但至少有这个合理的希望时间打印出来反射(reflect)执行指定计算的时间。

关于c++ - 奇怪的基准测试结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34557817/

相关文章:

spring-boot - WRK 基准测试 : Please explain results

c++ - 整数后缀 J 是什么意思?

c++ - 从缓冲区中获取最清晰的 iplimage

python - 如何将 Boost.Python 中的 map_indexing_suite 与自定义非 std 对象一起使用?

c++ - 委托(delegate)模板元编程的问题

c - GCC 不再实现 <varargs.h>

c - 后缀或操作数对于 gcc 的 `move' 无效

c++ - LinkedList在C++中只添加两个元素

profiling - 基准测试和分析之间的区别

ruby-on-rails - Redis 比 Postgres 快多少?