Interbench基准代码

时间:2015-01-16 20:00:45

标签: c linux windows benchmarking

我想问一下你们这里的任何人都熟悉这个功能,如下面的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;
}

2 个答案:

答案 0 :(得分:0)

我所知道的唯一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循环不足以消耗至少1微秒(如测量的那样),那么您将陷入无限循环,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()实际上与其参数的值成比例地起作用,你甚至不需要精确到毫秒精度。

答案 1 :(得分:-1)

您需要为Windows更改此代码。要在Windows上获得毫秒时间,您需要声明如下内容:

struct _timeb myTimeb;

然后使用

_ftime(&myTimeb);

以毫秒为单位的结果将在:

myTimeb.millitm

有关MSDN的详细信息,代码示例为:http://msdn.microsoft.com/en-us/library/z54t9z5f.aspx

我发现您已经尝试使用MSDN Sleep()了。希望你移植这个权利,因为它需要微秒作为参数,而Unix上的usleep()需要毫秒......我猜这个,因为你在调用中有* 1000,这将用于将毫秒转换为微秒,这是我以前见过的一个错误。

这不涉及burn_loop()