C++ 测量的执行时间是无意义的

问题描述 投票:0回答:1

我正在尝试通过使用泰勒级数、牛顿法、连分数等来击败 C++ 的

pow
函数,目标是比
pow
更快地获得良好的近似值。

我写了一些函数来与

pow
进行基准测试,我尝试使用
std::chrono::steady_clock
来测量执行时间。我的想法是运行该函数 1048576 次并将持续时间除以 1048576 以获得单次通过时间:

#include <chrono>
#include <cmath>
#include <iostream>
#include <string>

using std::chrono::steady_clock;
using std::chrono::duration;
using std::cout;

float newton(float base, int exp, int lim) {
    float i = 1.0 / exp;
    float r = 1 + (base - 1) / exp;
    exp--;
    for (int c = 0; c < lim; c++) {
        r = i * (exp * r + base / pow(r, exp));
    }
    return r;
}

int main()
{
    auto start = steady_clock::now();
    float r;
    for (int64_t i = 0; i < 1048576; i++) {
        r = newton(256.0, 3, 16);
    }
    auto end = steady_clock::now();
    duration<double, std::nano> time = end - start;
    cout << "newton(256, 3, 16): " << time.count() / 1048576 << " nanoseconds\n";
}

但是得到的测量值根本没有意义:

PS C:\Users\Xeni> C:\Users\Xeni\source\repos\exponentiation\x64\Release\exponentiation.exe
newton(256, 3, 16): 0 nanoseconds
PS C:\Users\Xeni> C:\Users\Xeni\source\repos\exponentiation\x64\Release\exponentiation.exe
newton(256, 3, 16): 9.53674e-05 nanoseconds
PS C:\Users\Xeni> C:\Users\Xeni\source\repos\exponentiation\x64\Release\exponentiation.exe
newton(256, 3, 16): 9.53674e-05 nanoseconds
PS C:\Users\Xeni> C:\Users\Xeni\source\repos\exponentiation\x64\Release\exponentiation.exe
newton(256, 3, 16): 9.53674e-05 nanoseconds

我的CPU运行在3GHz,即每秒30亿个时钟周期,因此一个时钟周期约为3.33333333333333E-10秒,如果结果可信,那么计算发生在大约1e-4纳秒内,即1e -13秒,不到一个时钟周期。

我使用 Visual Studio 2022 编译,编译器参数:

/permissive- /ifcOutput "x64\Release\" /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Ob1 /sdl /Fd"x64\Release\vc143.pdb" /Zc:inline /fp:fast /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /std:c17 /Gd /Oi /MD /std:c++20 /FC /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Ot /Fp"x64\Release\exponentiation.pch" /diagnostics:column

我在 PowerShell 中测量了整个程序的执行情况,计算出单次运行大约需要 8 纳秒(如果 PowerShell 正确的话):

PS C:\Users\Xeni> measure-command {C:\Users\Xeni\source\repos\exponentiation\x64\Release\exponentiation.exe}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 8
Ticks             : 89682
TotalDays         : 1.03798611111111E-07
TotalHours        : 2.49116666666667E-06
TotalMinutes      : 0.00014947
TotalSeconds      : 0.0089682
TotalMilliseconds : 8.9682



PS C:\Users\Xeni> 8.9682/1048576*1e6
8.55274200439453

我的代码有什么问题?我该如何解决它?

c++ execution-time
1个回答
-1
投票

正如我在评论中提到的。编译器看到

newton
函数并没有真正改变程序状态,并且返回值被忽略。并且每次的参数都相同。

一些快速且简单的随机性和累积

r
返回值是任何简单的解决方案。

int main()
{
    auto start = steady_clock::now();
    float r = 0;
    for (int64_t i = 0; i < 1048576; i++) {
        r += newton(256.0+rand()%40, 3, 16);
    }
    auto end = steady_clock::now();
    duration<double, std::nano> time = end - start;
    cout << "newton(256, 3, 16): " << time.count() / 1048576 << " nanoseconds\n";
    cout << "r for the sake of r: " << r << std::endl;
}
© www.soinside.com 2019 - 2024. All rights reserved.