【问题标题】:Interbench Benchmark CodeInterbench 基准代码
【发布时间】:2015-01-16 20:00:44
【问题描述】:

我想问你们这里的任何人都熟悉这个功能,如下面的Interbench。我想将此移植到 Windows 平台,但一直失败。我只能通过使用 timeval 而不是 timespec 来获得微秒精度。最后会出现错误:除以零和访问冲突异常

unsigned long get_usecs(struct timeval *myts)
{
    if (clock_gettime(myts))
        terminal_error("clock_gettime");

    return (myts->tv_sec * 1000000 + myts->tv_usec);
}

void burn_loops(unsigned long loops)
{
    unsigned long i;

    /*
    * We need some magic here to prevent the compiler from optimising
    * this loop away. Otherwise trying to emulate a fixed cpu load
    * with this loop will not work.
    */

    for (i = 0; i < loops; i++)
        _ReadWriteBarrier();
}
void calibrate_loop()
{
    unsigned long long start_time, loops_per_msec, run_time = 0;
    unsigned long loops;
    struct timeval myts;

    loops_per_msec = 100000;

redo:
    /* Calibrate to within 1% accuracy */
    while (run_time > 1010000 || run_time < 990000) {
        loops = loops_per_msec;
        start_time = get_usecs(&myts);
        burn_loops(loops);
        run_time = get_usecs(&myts) - start_time;
        loops_per_msec = (1000000 * loops_per_msec / run_time ? run_time : loops_per_msec );
    }

    /* Rechecking after a pause increases reproducibility */
    Sleep(1 * 1000);
    loops = loops_per_msec;
    start_time = get_usecs(&myts);
    burn_loops(loops);
    run_time = get_usecs(&myts) - start_time;

    /* Tolerate 5% difference on checking */
    if (run_time > 1050000 || run_time < 950000)
        goto redo;

    loops_per_ms = loops_per_msec;
}

【问题讨论】:

  • 您提供的函数很大程度上依赖于函数get_usecs() 来计算时间,并且它还依赖函数burn_loops()Sleep() 来实现其某些行为。 这些都不是标准的 C 甚至 POSIX 函数,所以你没有给我们足够的信息来提供适当的答案。
  • @JohnBollinger,我已经添加了所需的功能。

标签: c linux windows benchmarking


【解决方案1】:

我知道的唯一clock_gettime() 函数是 POSIX 指定的函数,并且该函数的签名与您正在使用的函数不同。它确实提供了纳秒级的分辨率(尽管不太可能提供单纳秒级的精度)。但是,据我所知,它在 Windows 上不可用。微软获得纳秒级时差的答案是使用其专有的"Query Performance Counter" (QPC) API。不过,请暂时把它放在一边,因为我怀疑时钟分辨率不是你真正的问题。

假设您的get_usecs() 函数成功地检索了具有微秒分辨率和至少(大约)毫秒精度的时钟时间,正如预期的那样,您的代码看起来有点奇怪。尤其是这个作业……

loops_per_msec = (1000000 * loops_per_msec / run_time
        ? run_time
        : loops_per_msec );

... 看起来很错误,当格式强调运算符优先级时更明显,如上所述(*/ 的优先级高于 ?:)。如果您没有获得可测量的正运行时间,它将为您提供除以零,否则它将始终为您提供与您开始时相同的 loops_per_msec 值或 run_time,后者不'甚至没有合适的单位。

我怀疑意图更像是这样......

loops_per_msec = ((1000000 * loops_per_msec)
        / (run_time ? run_time : loops_per_msec));

...,但这仍然有一个问题:如果 1000000 次循环不足以消耗至少一微秒(如测量值),那么您将陷入无限循环,loops_per_msec 反复设置为 1000000。

这将不太容易受到该特定问题的影响...

loops_per_msec = ((1000000 * loops_per_msec) / (run_time ? run_time : 1));

... 这对我来说也更有意义,因为如果测量的运行时间是 0 微秒,那么 1 微秒是比任何其他可能值更好的非零近似值。请注意,当测量的运行时间为零微秒时,这将非常迅速地(一百万倍)扩大您的 loops_per_msec。即使unsigned long long 有 128 位,你也不能多次这样做而不溢出,如果你得到一个溢出,那么你将进入一个无限循环。另一方面,如果发生溢出,则表明您尝试估计的 loops_per_msec 的正确值大得离谱。

这使我得出我的结论:我怀疑您的真正问题是您的时间计算错误或无效,要么是因为 get_usecs() 无法正常工作,要么是因为 burn_loops() 的主体正在被优化掉(尽管你努力避免这种情况)。您的时间测量不需要亚微秒级精度。事实上,您甚至不需要比毫秒精度更高的精度,只要您的 burn_loop() 确实与其参数的值成正比。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多