C中的单调时钟
Monotonic Clock in C
我正在为我的大学做一个算法项目。在项目中,我必须编写一些算法并使用 monotonic 时钟评估它们的时间。
我已经使用 C 实现了所有内容,但现在我遇到了时间测量方面的问题。
我目前正在使用 clock_gettime(CLOCK_MONOTONIC_RAW, ...)
获取时钟。来自 clock_gettime
的联机帮助页:
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments
or the incremental adjustments performed by adjtime(3). This clock does not count time that the system is sus‐
pended.
问题如下:这个时钟有时returns在完成这样的测量时为负值:
struct timespec start,end;
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
do{
// do stuff in here
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
} while((double) (end.tv_nsec - start.tv_nsec) <= *a certain quantity needed for precision*);
特别是,有时 end.tv_nsec - start.tv_nsec
是负数,这会导致程序循环进入此 do-while。
因为这个应该是一个单调时钟(永远不会倒退),所以不应该发生诸如经过时间为负的事情。但是,它似乎正在发生。
这个时钟真的单调吗?难道我做错了什么?我可以尝试找出问题所在吗?
我真的迷路了,在过去的几天里我尝试了很多东西并且 none 已经成功了。
如果需要更多代码,请参阅我的存储库:https://github.com/AlessandroZanatta/AlgorithmsProject/blob/dev/first_part/times.c
看看man timespec
有写着:
struct timespec {
time_t tv_sec;
long tv_nsec;
};
The tv_sec member is again the elapsed time in whole seconds.
The tv_nsec member represents the rest of the elapsed time in nanoseconds.
所以tv_nsec
只是时间的rest,不能用整秒来表示,所以你需要减去秒和纳秒。
减去时间规格
这里也https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.5/html_node/Elapsed-Time.html给出了两个struct timeval
类型的值相减的“最佳方式”,如下:
(对于 struct timespec
,只需将 timespec
替换为 timeval
,将 tv_nsec
替换为 tv_usec
,将 1000000000
替换为 1000000
。 )
It is often necessary to subtract two values of type struct timeval or struct timespec. Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.
/* Subtract the `struct timeval' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */
int
timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
我正在为我的大学做一个算法项目。在项目中,我必须编写一些算法并使用 monotonic 时钟评估它们的时间。
我已经使用 C 实现了所有内容,但现在我遇到了时间测量方面的问题。
我目前正在使用 clock_gettime(CLOCK_MONOTONIC_RAW, ...)
获取时钟。来自 clock_gettime
的联机帮助页:
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments
or the incremental adjustments performed by adjtime(3). This clock does not count time that the system is sus‐
pended.
问题如下:这个时钟有时returns在完成这样的测量时为负值:
struct timespec start,end;
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
do{
// do stuff in here
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
} while((double) (end.tv_nsec - start.tv_nsec) <= *a certain quantity needed for precision*);
特别是,有时 end.tv_nsec - start.tv_nsec
是负数,这会导致程序循环进入此 do-while。
因为这个应该是一个单调时钟(永远不会倒退),所以不应该发生诸如经过时间为负的事情。但是,它似乎正在发生。
这个时钟真的单调吗?难道我做错了什么?我可以尝试找出问题所在吗?
我真的迷路了,在过去的几天里我尝试了很多东西并且 none 已经成功了。 如果需要更多代码,请参阅我的存储库:https://github.com/AlessandroZanatta/AlgorithmsProject/blob/dev/first_part/times.c
看看man timespec
有写着:
struct timespec { time_t tv_sec; long tv_nsec; };
The tv_sec member is again the elapsed time in whole seconds. The tv_nsec member represents the rest of the elapsed time in nanoseconds.
所以tv_nsec
只是时间的rest,不能用整秒来表示,所以你需要减去秒和纳秒。
减去时间规格
这里也https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.5/html_node/Elapsed-Time.html给出了两个struct timeval
类型的值相减的“最佳方式”,如下:
(对于 struct timespec
,只需将 timespec
替换为 timeval
,将 tv_nsec
替换为 tv_usec
,将 1000000000
替换为 1000000
。 )
It is often necessary to subtract two values of type struct timeval or struct timespec. Here is the best way to do this. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.
/* Subtract the `struct timeval' values X and Y, storing the result in RESULT. Return 1 if the difference is negative, otherwise 0. */ int timeval_subtract (result, x, y) struct timeval *result, *x, *y; { /* Perform the carry for the later subtraction by updating y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. tv_usec is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; }