0
#include <windows.h>
#include <stdio.h>
#include <stdint.h>

// assuming we return times with microsecond resolution
#define STOPWATCH_TICKS_PER_US  1

uint64_t GetStopWatch()
{
    LARGE_INTEGER t, freq;
    uint64_t val;

    QueryPerformanceCounter(&t);
    QueryPerformanceFrequency(&freq);
    return (uint64_t) (t.QuadPart / (double) freq.QuadPart * 1000000);
}

void task()
{
    printf("hi\n");
}

int main()
{
  uint64_t start = GetStopWatch();
  task();
  uint64_t stop = GetStopWatch();

  printf("Elapsed time (microseconds): %lld\n", stop - start);
}

以上包含查询性能计数器函数检索高分辨率性能计数器的当前值和查询性能频率函数检索高分辨率性能计数器的频率。如果我正在调用任务();函数多次,然后开始和停止时间之间的差异会有所不同,但我应该得到相同的时间差来多次调用任务函数。谁能帮我找出上面代码中的错误?

4

2 回答 2

1

问题是,Windows 是一个先发制人的多任务操作系统。你问这到底是什么意思?

'简单' - windows 为系统中每个正在运行的进程分配时间片。这给人以数十或数百个进程并行运行的错觉。实际上,在典型的台式机/笔记本电脑中,您仅限于 2、4、8 或 16 个并行进程。Intel i3 有 2 个物理核心,每个核心都可以给人一种同时做两件事的印象。(但实际上,有一些硬件技巧可以在每个内核可以同时处理的两个线程之间切换执行)这是对 Windows/Linux/MacOSX 所做的软件上下文切换的补充。

这些时间片不保证每次都具有相同的持续时间。您可能会发现 pc 与 windows.time 同步以更新您的时钟,您可能会发现病毒扫描程序决定开始工作,或其他任何事情。所有这些事件都可能发生在你的 task() 函数开始之后,但在它结束之前。

在 DOS 时代,每次对 task() 的单次迭代计时,都会得到几乎相同的结果。不过,多亏了 TSR 程序,您仍然可以发现一个中断被触发并且在执行期间一些机器时间被窃取。

正是出于这些原因,可以通过运行任务 N 次,将经过的时间除以 N 以获得每次迭代的时间来计算更准确地确定任务执行所需的时间。

对于过去的某些函数,我使用的 N 值高达 1 亿。

编辑:一个简短的片段。

LARGE_INTEGER tStart, tEnd;
LARGE_INTEGER tFreq;
double tSecsElapsed;
QueryPerformanceFrequency(&tFreq);
QueryPerformanceCounter(&tStart);

int i, n = 100;
for (i=0; i<n; i++)
{
// Do Something
}

QueryPerformanceCounter(&tEnd);
tSecsElapsed = (tEnd.QuadPart - tStart.QuadPart) / (double)tFreq.QuadPart;
double tMsElapsed = tSecElapsed * 1000;

double tMsPerIteration = tMsElapsed / (double)n;
于 2013-11-11T09:55:38.530 回答
1

现代操作系统和处理器上的代码执行时间是非常不可预测的。没有任何情况可以确定经过的时间实际上测量了代码所花费的时间,您的程序很可能在执行时将处理器丢给了另一个进程。处理器使用的缓存起着很大的作用,当缓存中还没有包含程序使用的代码和数据时,第一次执行代码时总是会慢很多。与处理器相比,内存总线非常慢。

当您测量 printf() 语句时,它变得特别没有意义。控制台窗口由另一个进程拥有,因此有很大一部分进程互操作开销,其执行时间严重取决于该进程的状态。例如,当需要滚动控制台窗口时,您会突然看到巨大的差异。最重要的是,实际上你无法做任何事情来让它更快,所以测量它只是为了好奇。

仅概要分析您可以改进的代码。采集许多样本,这样您就可以摆脱异常值。永远不要选择最低的测量值,这只会产生不切实际的期望。也不要选择平均值,这会受到其他进程在您的测试中可能产生的长时间延迟的很大影响。中是一个不错的选择。

于 2013-11-11T12:33:08.330 回答