当我输出gettimeofday()
的微秒字段时,我注意到微秒字段大于1,000,000。有人知道为什么吗?这是否意味着我一直在解释gettimeofday()
错误?
对于记录,我的假设是根据gettimeofday()
的当前时间(以微秒为单位)如下:
struct timeval ts;
gettimeofday(&ts, NULL);
printf("%zu", ts.tv_sec * 1000000 + ts.tv_usec);
编辑:这是导致问题的代码。在下面的注释之后,printf()可能出错了。
struct timeval curr_time;
gettimeofday(&curr_time, NULL);
printf("Done-arino! Onto the matrix multiplication (at %zu s, %03zu ms)\n", curr_time.tv_sec, curr_time.tv_usec);
// Matrix Multiplication
struct timeval start_tv, end_tv, elapsed_tv;
gettimeofday(&start_tv, NULL);
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
for (k = 0; k < N; k++)
C[i][j] += A[i][k] * B[k][j];
gettimeofday(&end_tv, NULL);
timersub(&end_tv, &start_tv, &elapsed_tv);
// Print results
printf("Elapsed time: %zu s, %03zu ms\n", elapsed_tv.tv_sec, elapsed_tv.tv_usec / 1000);
答案 0 :(得分:0)
成功到gettimeofday
后,是的,tv_usec
保证严格小于1000000。
如果你(认为你)看到1000000或更高的值,那么是的,你可能做错了。
一个常见的错误是天真地添加或减去两个struct timeval
值,而没有在tv_sec
和tv_usec
字段之间实现正确的携带或借用,这很容易导致(错误和tv_usec
中的值大于1000000。(在您编辑的帖子中,您提到减去时间规格,但您正在使用系统提供的timersub
函数,该函数应该获得正确的借用。)
如果你使用的是struct timespec
而不是struct timeval
,而如果正在进行闰秒,而如果则是(奇迹般的) )使用一个OS内核实现了Markus Kuhn在https://www.cl.cam.ac.uk/~mgk25/posix-clocks.html提出的CLOCK_UTC
时钟类型,你会看到tv_nsec
值大于1000000000,但那是很多“if”s。 (据我所知,没有广泛使用的内核曾经实现过CLOCK_UTC
。)
答案 1 :(得分:0)
您需要展示一些更有说服力的代码,并找出遇到此问题的平台。
例如:
#include <stdio.h>
#include <sys/time.h>
int main(void)
{
while (1)
{
struct timeval ts;
if (gettimeofday(&ts, 0) == 0 && ts.tv_usec >= 1000000)
printf("%lu s; %lu µs\n", (long)ts.tv_sec, (long)ts.tv_usec);
}
return 0;
}
非常繁忙的循环有点令人讨厌;也许你应该在每次迭代时使用nanosleep()
睡一微秒或两秒:
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
int main(void)
{
while (1)
{
struct timeval tv;
if (gettimeofday(&tv, 0) == 0 && tv.tv_usec >= 1000000)
printf("%lu s; %lu µs\n", (long)tv.tv_sec, (long)tv.tv_usec);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 2000 };
nanosleep(&ts, 0);
}
return 0;
}
或者,包括一个进度表来证明代码正在运行:
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
int main(void)
{
size_t loop_count = 0;
size_t line_count = 0;
while (1)
{
struct timeval tv;
if (gettimeofday(&tv, 0) == 0 && tv.tv_usec >= 1000000)
printf("%lu s; %lu µs\n", (long)tv.tv_sec, (long)tv.tv_usec);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 2000 };
nanosleep(&ts, 0);
if (++loop_count > 100000)
{
loop_count = 0;
putchar('.');
line_count++;
if (line_count >= 50)
{
putchar('\n');
line_count = 0;
}
fflush(stdout);
}
}
return 0;
}
timersub()
在Ubuntu 16.04 LTS VM上,我可以找到包含宏的文件/usr/include/x86_64-linux-gnu/sys/time.h
:
# define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
我可以看到的所有迹象都是如果是这种情况,则tv_usec
是__u32
,是无符号数量。< 0
条件永远不会是真的,你有时可能会看到奇怪的大正值。当然是YMMV。
即使我的里程也不尽相同
进一步审查表明,虽然__u32
似乎使用tv_usec
标题,但这些标题不是主系统标题。
/usr/include/linux/time.h: __kernel_suseconds_t tv_usec; /* microseconds */
/usr/include/linux/can/bcm.h: long tv_usec;
/usr/include/drm/exynos_drm.h: __u32 tv_usec;
/usr/include/drm/exynos_drm.h: __u32 tv_usec;
/usr/include/drm/vmwgfx_drm.h: uint32_t tv_usec;
/usr/include/drm/drm.h: __u32 tv_usec;
/usr/include/rpc/auth_des.h: uint32_t tv_usec; /* Microseconds. */
/usr/include/valgrind/vki/vki-darwin.h:#define vki_tv_usec tv_usec
/usr/include/valgrind/vki/vki-linux.h: vki_suseconds_t tv_usec; /* microseconds */
/usr/include/rpcsvc/rstat.x: unsigned int tv_usec; /* and microseconds */
/usr/include/rpcsvc/rstat.h: u_int tv_usec;
/usr/include/x86_64-linux-gnu/bits/utmpx.h: __int32_t tv_usec; /* Microseconds. */
/usr/include/x86_64-linux-gnu/bits/time.h: __suseconds_t tv_usec; /* Microseconds. */
/usr/include/x86_64-linux-gnu/bits/utmp.h: int32_t tv_usec; /* Microseconds. */
/usr/include/x86_64-linux-gnu/sys/time.h: (ts)->tv_nsec = (tv)->tv_usec * 1000; \
/usr/include/x86_64-linux-gnu/sys/time.h: (tv)->tv_usec = (ts)->tv_nsec / 1000; \
/usr/include/x86_64-linux-gnu/sys/time.h:# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
/usr/include/x86_64-linux-gnu/sys/time.h:# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
/usr/include/x86_64-linux-gnu/sys/time.h: ((a)->tv_usec CMP (b)->tv_usec) : \
/usr/include/x86_64-linux-gnu/sys/time.h: (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
/usr/include/x86_64-linux-gnu/sys/time.h: if ((result)->tv_usec >= 1000000) \
/usr/include/x86_64-linux-gnu/sys/time.h: (result)->tv_usec -= 1000000; \
/usr/include/x86_64-linux-gnu/sys/time.h: (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
/usr/include/x86_64-linux-gnu/sys/time.h: if ((result)->tv_usec < 0) { \
/usr/include/x86_64-linux-gnu/sys/time.h: (result)->tv_usec += 1000000; \
令人担心的是,对于具有该名称的成员,任何代码都使用无符号类型,但这并不意味着代码使用struct timeval
和timersub()
。
此代码:
#include <sys/time.h>
#include <stdio.h>
int main(void)
{
struct timeval t = { .tv_sec = 0, .tv_usec = -1 };
printf("%ld %ld\n", (long)t.tv_sec, (long)t.tv_usec);
return 0;
}
编译为64位(因此long
足够大,可以保存tv_usec
可以定义的任何内容)打印0 -1
。可以将tv_usec
成员初始化为0
,递减它,并验证它是否定的,以及各种其他相关测试。
所以,问题并不像“timersub()
错误”那么简单 - 这是一种巨大的解脱。
答案 2 :(得分:0)
您的printf
格式是可疑的,可能会导致此问题。
%zu
格式用于打印size_t
值。但tv_sec
和tv_usec
都没有size_t
类型。
在现代系统中,size_t
可能是64位。但如果tv_sec
或tv_usec
不是printf
,printf
将错误地打印这些值。
我将您的printf("Done-arino! Onto the matrix multiplication (at %ld s, %03u ms)\n",
curr_time.tv_sec, curr_time.tv_usec);
更改为
printf("Elapsed time: %ld s, %03u ms\n",
elapsed_tv.tv_sec, elapsed_tv.tv_usec / 1000);
和
tv_sec
但这些对您来说不一定是正确的 - 这取决于您的系统对tv_usec
和var app = angular.module('app', []);
app.component('foo', {
template: '<input ng-model="$ctrl.fooValue" enter-key="$ctrl.onEnter()" />',
controller: function() {
this.onEnter = function() {
// this.fooValue is not updated with input value
};
},
bindings: {
fooValue: '@'
}
});
app.directive('enterKey', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind("keydown keypress", function(event) {
var keyCode = event.which || event.keyCode;
// If enter key is pressed
if (keyCode === 13) {
scope.$apply(function() {
// Evaluate the expression
scope.$eval(attrs.enterKey);
});
}
});
}
};
});
describe('test', function() {
describe('foo', function() {
beforeEach(module('app'));
var element,
inputElem;
beforeEach(inject(function($compile, $rootScope) {
var fooScope = $rootScope.$new();
element = angular.element('<foo foo-value="foo1"></foo>');
element = $compile(element)(fooScope);
fooScope.$digest();
}));
it('should set fooValue with foo3', function() {
var controller = element.controller('foo');
inputElem = element.find('input');
inputElem.val('foo3');
inputElem.triggerHandler({
type: 'keydown',
which: 13
});
expect(controller.fooValue).toBe('foo3');
});
});
});
的具体选择。