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