【问题标题】:C/C++ Measuring Program EfficiencyC/C++ 测量程序效率
【发布时间】:2016-03-08 02:14:33
【问题描述】:

我认为衡量我的程序效率的最佳方法是检查它运行所花费的时间,但是当我这样做时,我总是得到随机时间。

我正在使用 Roger Pate 在this 这个线程中显示的以下代码:

#include <ctime>

void func()
{
    using namespace std;
    clock_t begin = clock();

    //Function to measure here

    clock_t end = clock();
    double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

我认为这是因为我有一些程序在后台运行。

我不想每次想重新检查我的功能的时间时都重新启动计算机,所以我的问题是:有没有更好的方法来衡量程序的效率?

IDE 是 Codeblocks,OS 是 Win7 64bit。

【问题讨论】:

  • 这些可能是:1. 优化相关(可能您测量的代码已被优化掉......在这种情况下结果无效),2. 堆栈内存覆盖(您的结果无效) , 3. 上下文切换 / IO 相关问题(这些是原子操作,锁争用可能会极大地改变性能,因此结果是有效的,但会有所不同)等等...... 请发布一个实际显示的示例代码问题
  • 您看到的典型时间是什么时候?
  • @CaptainGiraffe 很确定它是CLOCKS_PER_SEC
  • @Qix 哎呀。也不能编辑。 不要为此使用clock()。并记住正确拼写您的定义。后果可能是可怕的
  • 使用clock_gettime()CLOCK_PROCESS_CPUTIME_ID 作为第一个参数。这仅返回在当前进程中花费的时间。开始时间调用一次,结束时间再调用一次。阅读手册页了解详细信息

标签: c++ c performance


【解决方案1】:

使用现代的数千兆赫兹 CPU 和高速 RAM I/O,除非您的代码运行时间超过几分钟左右,否则测量其执行时间不太可能产生任何有意义的结果。信噪比太高了。 I/O 中断和自然的抢先式多任务处理会产生过多的噪音,并淹没任何有意义的运行时指标。

尤其是在您的情况下,在 MS Windows 上,它不断启动各种后台 O/S 进程。重新启动计算机只会让事情变得更糟。 Windows O/S 通常会在重启后在接下来的几分钟内启动大量后台进程,这些进程会做一件事或另一件事。通常您需要等待 10-15 分钟,自然背景活动才会平静下来。

【讨论】:

    【解决方案2】:

    您需要测量用户时间。您可以在基于 UNIX 的系统 (https://en.wikipedia.org/wiki/Time_(Unix)) 中使用 time 命令完成此操作。我不确定微软是否有类似的东西。

    用户时间是操作系统为您的进程测量的时间,因此它更准确地描述了您的程序运行了多长时间。它之所以能够做到这一点,是因为它是实体调度任务。

    【讨论】:

      【解决方案3】:

      如果您担心 I/O 中断或抢占式多任务的噪音,请使用 GetThreadTimes 函数。

      不过,我更关心clock() 函数的分辨率。在 Windows 上,我会使用 QueryPerformanceCounter 函数。

      【讨论】:

        【解决方案4】:

        正如其他人已经指出的那样,使用 clock() 是一种不精确的时间测量方式,更好的方法是直接查询 TSC 计数器。 TSC 计数器非常准确,查询速度很快,并且能够测量单个指令的执行速度(受一些限制,如下所示)。

        作为查询TSC的例子,见下面的代码;

        #ifdef WIN32
        #define uint64_t unsigned __int64
        #endif 
        
        static inline uint64_t rdtsc (void) {
          static struct {
            union {
              struct { uint32_t hi; uint32_t lo; };
              uint64_t ret;
            };
          } tsc;
          asm volatile (
            "RDTSCP\n\t"
            "mov %%edx, %0\n\t"
            "mov %%eax, %1\n\t"
            : "=r" (tsc.lo), "=r" (tsc.hi)
            :: "%rax", "%rbx", "%rcx", "%rdx"
          );
          return tsc.ret;
        }
        
        // example: uint64_t start = rdtsc();
        //          // Code goes here 
        //          uint64_t end   = rdtsc();
        //  printf("Code executed in %zd cycles\n", end-start);
        

        使用 TSC 计数器的唯一警告是,TSC 仅在您正在使用的内核上准确,因此对于中断驱动的工作负载或长时间运行的进程,您最好查询系统时间计数器。很久以前,TSC 计数器也受处理器运行频率的影响。

        TLDR;使用 TSC 测量短 sn-ps 代码的运行时间。

        【讨论】:

          【解决方案5】:

          这是我在这里的第一次行动,所以请善待。

          1) 如前所述,对于计时器的“较低”精度(在我们周围),QueryPerformanceCounter() 函数可以正常工作。此外,您应该询问此计时器使用 QueryPerformanceFrequency() 步进的频率。然后您可以确定从开始到结束的滴答声的差异并将其除以频率。

          2)更高的分辨率(也提到)是直接读取您机器的TSC(TimeStampCounter)寄存器。命令 _rdtscp() 是在 windows (afaik) 下执行此操作的最佳方法。这里的困难是确定您的机器当前运行的频率。一种方法是测量用于 sleep(1000) 的滴答声,然后通过简单地将滴答声差作为以赫兹为单位的频率来确定频率。

          1) 的示例代码

          #include "Windows.h"
          
          _LARGE_INTEGER Start,Stop,Frequency;
          
          DWORD64 Time_taken;
          
          int YourFunction ()
          {
           Start = QueryPerformanceCounter();
          
           // Run Code to measure here
          
           Stop = QueryPerformanceCounter();
          
           Frequency = QueryPerformanceFrequency();
          
           Time_taken = (Stop.QuadPart-Start.QuadPart)/Frequency.QuadPart;
           }
          

          对于 2)

           #include <intrin.h> 
           #include <stdio.h>
          
           unsigned __int64 Start,Stop,Frequency,Time_taken;   // Variables for measurement
           unsigned int test;    // Pointer-buffer for Machine AUX register (non-relevant)
          
           int YourFunction(void) 
           {
            // Measure current frequency
           Start = __rdtscp(&test);
          
           Sleep(1000);
          
           Stop = __rdtscp(&test);
          
           Frequency = Stop-Start;
          
           // Measure your function
           Start = __rdtscp(&test);
          
           // Code to measure
          
           Stop = __rdtscp(&test);
          
           Time_taken = (Stop-Start)/Frequency;
           }
          

          参考见 1) https://msdn.microsoft.com/de-de/library/windows/desktop/ms644904%28v=vs.85%29.aspx

          和 2) https://msdn.microsoft.com/de-de/library/bb385235.aspx

          我希望这能回答你的问题。

          你好,萨沙

          【讨论】:

            【解决方案6】:

            在分析器下运行您的代码,代码可以优化但带有调试信息。

            对 VerySleepy 有很好的体验:http://www.codersnotes.com/sleepy/

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-02-16
              • 1970-01-01
              • 2010-12-22
              • 1970-01-01
              • 2011-08-04
              • 2022-10-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多