【问题标题】:Execution time of a short function c++短函数c ++的执行时间
【发布时间】:2015-02-26 13:34:40
【问题描述】:

我想计算一个非常小的函数的执行时间来比较递归函数和迭代函数的执行时间。

当然,clock() 在分辨率不够的情况下根本无法做到这一点。你能告诉我如何使用其他时间源,如GetThreadTimes()。我在微软网站上看到了一个描述,但是没看懂原理。

另外,<chrono> 标头在 MS Visual 10 中也不起作用。

代码:

int search (int a[], int size, int& num) {

if (size >0) {

    if (a[size-1] == 17) {num = size-1; return num;}
    else {return search (a, --size, num);}}
else {return num=-1;};
}

int searchit (int a[], int size, int& num) {

    for (int i =0; i< size; i++) {
        if (a[i] == 17) {num = i;}
        else num = -1;
    }
    return num;}


int main () {
    srand ((unsigned int) time(0));
    int num = 0;
    const int size = 40;
    int a[size];
    for (int i =0; i< size; i++) {

        a[i] = rand()%100;
        cout << a[i] << endl;}
    cout << '\n';

    search (a, size, num);

    cout << num << endl;

    cin.get();
    cin.ignore();
}

【问题讨论】:

标签: c++ time execution


【解决方案1】:

一种解决方案是按照@amchacon 的建议进行多次迭代。这样做的好处是简单明了。

由于编译器对内联和/或指令流水线使用不同的启发式方法,以及由于在第一次迭代后指令和数据缓存都已预热,它的缺点可能导致不准确或不正确的结果。
因此,虽然由于内存访问模式错误(可能导致两打缓存未命中,每次花费 500 个周期),您的函数的性能确实可能很差,但当您运行该函数一百次时,这可能根本不会显示,如果总数一组缓存行适合缓存。

有哪些替代方案?

a) 不适用于您的问题(因为您想测试递归算法),但无论如何我都会针对“一般”情况说明:使用IACA。它专为对一小段代码到指令进行微基准测试而设计。

b) 使用精度更高的计时器或使用一个完全不是计时器的计时器。为此,您可以在 Windows 下使用 QueryPerformanceCounterQueryThreadCycleTime(Vista 及更高版本)。周期可能比时间更可取,具体取决于您要测量的内容。

c) 查询thread times。在我看来,这是最好的方法,因为您可以获得可靠、精确、准确的时间(与计时器不同,它可能包括上下文切换和在其他进程中花费的时间!),它适用于任何类型的代码,让您区分内核和用户时间,以防您的代码调用系统函数,并区分 CPU 时间和挂起时间。
在运行您的函数之前和之后调用一次GetThreadTimes,并减去相应的UserTimeKernelTime 值。
或者,如果您也对挂墙时间感兴趣,则启动一个工作线程(对于挂墙时间,您将从ExitTime 中减去CreationTime,显然您只会得到一个有效的ExitTime 线程之后已退出!)。如果您的代码还涉及阻塞 I/O 操作,那么计算挂起时间可能很有用。

【讨论】:

  • 在问这个问题之前,我已经阅读了关于 GetThreadTimes 的内容。但是我很困惑如何使用它。例如,这里 (codeproject.com/Articles/175033/An-eternal-question-of-timing) 描述了一种非常重要的方式。您能就此提出建议吗?
  • 除非你有大量线程并且想要考虑并行执行,否则它并没有那么大,真的。 GetThreadTimes 所做的只是返回一个特定线程(由句柄给出)实际运行的时间,分辨率为 100 纳秒(尽管精度可能较低)。尽管 WinAPI 名称令人生畏,但它们实际上只是 uint64_t 值,每个编译器都可以本机减去它们(是的,这是草率且不可移植的,但是 bleh)。要为您自己的线程计时,句柄是 GetCurrentThread()(HANDLE) -1,否则它是您从生成工作线程中获得的句柄。
  • 只有当你在游戏中加入并发时它才会变得复杂(但不是太多,真的)。请注意,虽然看起来很有趣,但如果您有并发性,线程时间大于总时间是完全正常的(也就是说,如果两个线程以 100% 运行,当程序只运行 5 秒时,您将有 10 秒的线程时间秒)。当然,这只是正常的——你有 5 秒,但有两个线程。
【解决方案2】:

只需进行 100 次搜索并取平均值:

    time_t begin,end,total;
    const int iterations = 100;
    begin = clock();

    for (int i = 0;i<iterations;i++)
     search (a, size, num);

    end = clock();
    total = (end-begin)/static_cast<double>(CLOCKS_PER_SEC);

    cout<<"Average time for "<<iterations<<" iterations: "<<total/iterations<<endl;

编译器将展开 for 循环 :)。反正For循环的消耗可以忽略不计。

【讨论】:

    猜你喜欢
    • 2013-03-27
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多