gettimeofday 函数的精度是多少?
What is the precision of the gettimeofday function?
我正在阅读 OSTEP 的第 single.dvi 章。在作业部分,它说:
One thing you’ll have to take into account is the precision and accuracy of your timer. A typical timer that you can use is gettimeofday();
read the man page for details. What you’ll see there is that gettimeofday()
returns the time in microseconds since 1970; however, this does not mean
that the timer is precise to the microsecond. Measure back-to-back calls
to gettimeofday()
to learn something about how precise the timer re-
ally is; this will tell you how many iterations of your null system-call
test you’ll have to run in order to get a good measurement result. If
gettimeofday()
is not precise enough for you, you might look into
using the rdtsc
instruction available on x86 machines
我写了一些代码来测试调用 gettimeofday()
函数的成本如下:
#include <stdio.h>
#include <sys/time.h>
#define MAX_TIMES 100000
void m_gettimeofday() {
struct timeval current_time[MAX_TIMES];
int i;
for (i = 0; i < MAX_TIMES; ++i) {
gettimeofday(¤t_time[i], NULL);
}
printf("seconds: %ld\nmicro_seconds: %ld\n", current_time[0].tv_sec, current_time[0].tv_usec);
printf("seconds: %ld\nmicro_seconds: %ld\n", current_time[MAX_TIMES - 1].tv_sec, current_time[MAX_TIMES - 1].tv_usec);
printf("the average time of a gettimeofday function call is: %ld us\n", (current_time[MAX_TIMES - 1].tv_usec - current_time[0].tv_usec) / MAX_TIMES);
}
int main(int argc, char *argv[]) {
m_gettimeofday();
return 0;
}
但是,输出将始终为 0 微秒。 gettimeofday()
函数的精度似乎恰好是一微秒。我的测试代码有什么问题?还是我误解了作者的意思?感谢您的帮助!
连续调用 gettimeofday
的平均微秒通常 小于一微秒 - 在我的机器上它介于 0.05 和 0.15 之间。
现代 CPU 通常 运行 GHz 速度 - 即每秒 十亿 条指令,因此两条连续指令的数量级应为纳秒,而不是微秒(显然,对 gettimeofday
这样的函数的两次调用比两个简单的操作码更复杂,但它仍应占用数十纳秒的数量级,而不是更多。
但是你正在执行 int
s 的除法 - 用 (current_time[MAX_TIMES - 1].tv_usec - current_time[0].tv_usec)
除以 MAX_TIMES
- 在 C 中也将 return 和 int
,在这种情况下 0.
要获得实际测量值,除以 (double)MAX_TIMES
(并将结果打印为双精度):
printf("the average time of a gettimeofday function call is: %f us\n", (current_time[MAX_TIMES - 1].tv_usec - current_time[0].tv_usec) / (double)MAX_TIMES);
作为奖励 - 在 Linux 系统上 gettimeofday
如此之快的原因(您可能会认为它是一个更复杂的函数,调用内核并产生系统调用的开销)这要归功于一个名为 vdso 的特殊功能,它允许内核向用户 space 提供信息,而无需通过内核。
gettimeofday(2)
已代表 clock_gettime(2)
宣布过时,它比旧版本具有更好的分辨率(它使用纳秒级分辨率)
精度是另一个问题(不同),因为它取决于硬件如何允许您获取时间戳以及操作系统如何实现它。
在基于 linux/intel 的系统中,通常有很好的硬件可用,并且 linux 很好地实现了它,因此在处理时间戳时通常可以获得真正的纳秒级精度。但是不要试图在石英振荡器较差且未经过 PPS sincronized 的机器中获得这种精度。你没有指定你需要获取什么样的时间戳,但是如果你需要获取绝对时间戳,与官方时间进行比较,不要期望它们接近几百毫秒(基于 NTP syncronized带有普通石英振荡器的机器)
无论如何,要获得您安排的通话的平均时间,您有两个问题:
- 你需要调用
MAX_TIMES + 1
次你的 gettimeofday(2)
系统调用,因为你正在测量两个时间戳之间的时间(所以你计算你调用系统调用和它能够获取时间戳,并且从时间戳到 return 值的时间被传递给调用例程 --- 但顺序相反)执行此操作的最佳方法是获取时间戳 t0
在开头,MAX_TIMES
时间戳在 t1
中。只有这样,您才能确定 t0
到 t1
之间的时间并将其划分为 MAX_TIMES
。为此,从 t1.tv_usec
中减去 t0.tv_usec
,如果结果小于零,则添加 1000000
,并增加 t1.tv_sec - t0.tv_sec
中的差值。 tv_sec
将有秒的差异,而 tv_usec
将有超过秒的微秒。
- 这是假设系统调用开销不变,但事实并非如此。有时系统调用比其他的花费更多的时间,你感兴趣的值不是它们的平均值,而是它能达到的最小值。但是你可以符合平均值,因为你不会进入 usec 分辨率下。
无论如何,我建议您使用 clock_gettime(2)
系统调用,因为它具有纳秒分辨率。
我正在阅读 OSTEP 的第 single.dvi 章。在作业部分,它说:
One thing you’ll have to take into account is the precision and accuracy of your timer. A typical timer that you can use is
gettimeofday();
read the man page for details. What you’ll see there is thatgettimeofday()
returns the time in microseconds since 1970; however, this does not mean that the timer is precise to the microsecond. Measure back-to-back calls togettimeofday()
to learn something about how precise the timer re- ally is; this will tell you how many iterations of your null system-call test you’ll have to run in order to get a good measurement result. Ifgettimeofday()
is not precise enough for you, you might look into using therdtsc
instruction available on x86 machines
我写了一些代码来测试调用 gettimeofday()
函数的成本如下:
#include <stdio.h>
#include <sys/time.h>
#define MAX_TIMES 100000
void m_gettimeofday() {
struct timeval current_time[MAX_TIMES];
int i;
for (i = 0; i < MAX_TIMES; ++i) {
gettimeofday(¤t_time[i], NULL);
}
printf("seconds: %ld\nmicro_seconds: %ld\n", current_time[0].tv_sec, current_time[0].tv_usec);
printf("seconds: %ld\nmicro_seconds: %ld\n", current_time[MAX_TIMES - 1].tv_sec, current_time[MAX_TIMES - 1].tv_usec);
printf("the average time of a gettimeofday function call is: %ld us\n", (current_time[MAX_TIMES - 1].tv_usec - current_time[0].tv_usec) / MAX_TIMES);
}
int main(int argc, char *argv[]) {
m_gettimeofday();
return 0;
}
但是,输出将始终为 0 微秒。 gettimeofday()
函数的精度似乎恰好是一微秒。我的测试代码有什么问题?还是我误解了作者的意思?感谢您的帮助!
连续调用 gettimeofday
的平均微秒通常 小于一微秒 - 在我的机器上它介于 0.05 和 0.15 之间。
现代 CPU 通常 运行 GHz 速度 - 即每秒 十亿 条指令,因此两条连续指令的数量级应为纳秒,而不是微秒(显然,对 gettimeofday
这样的函数的两次调用比两个简单的操作码更复杂,但它仍应占用数十纳秒的数量级,而不是更多。
但是你正在执行 int
s 的除法 - 用 (current_time[MAX_TIMES - 1].tv_usec - current_time[0].tv_usec)
除以 MAX_TIMES
- 在 C 中也将 return 和 int
,在这种情况下 0.
要获得实际测量值,除以 (double)MAX_TIMES
(并将结果打印为双精度):
printf("the average time of a gettimeofday function call is: %f us\n", (current_time[MAX_TIMES - 1].tv_usec - current_time[0].tv_usec) / (double)MAX_TIMES);
作为奖励 - 在 Linux 系统上 gettimeofday
如此之快的原因(您可能会认为它是一个更复杂的函数,调用内核并产生系统调用的开销)这要归功于一个名为 vdso 的特殊功能,它允许内核向用户 space 提供信息,而无需通过内核。
gettimeofday(2)
已代表 clock_gettime(2)
宣布过时,它比旧版本具有更好的分辨率(它使用纳秒级分辨率)
精度是另一个问题(不同),因为它取决于硬件如何允许您获取时间戳以及操作系统如何实现它。
在基于 linux/intel 的系统中,通常有很好的硬件可用,并且 linux 很好地实现了它,因此在处理时间戳时通常可以获得真正的纳秒级精度。但是不要试图在石英振荡器较差且未经过 PPS sincronized 的机器中获得这种精度。你没有指定你需要获取什么样的时间戳,但是如果你需要获取绝对时间戳,与官方时间进行比较,不要期望它们接近几百毫秒(基于 NTP syncronized带有普通石英振荡器的机器)
无论如何,要获得您安排的通话的平均时间,您有两个问题:
- 你需要调用
MAX_TIMES + 1
次你的gettimeofday(2)
系统调用,因为你正在测量两个时间戳之间的时间(所以你计算你调用系统调用和它能够获取时间戳,并且从时间戳到 return 值的时间被传递给调用例程 --- 但顺序相反)执行此操作的最佳方法是获取时间戳t0
在开头,MAX_TIMES
时间戳在t1
中。只有这样,您才能确定t0
到t1
之间的时间并将其划分为MAX_TIMES
。为此,从t1.tv_usec
中减去t0.tv_usec
,如果结果小于零,则添加1000000
,并增加t1.tv_sec - t0.tv_sec
中的差值。tv_sec
将有秒的差异,而tv_usec
将有超过秒的微秒。 - 这是假设系统调用开销不变,但事实并非如此。有时系统调用比其他的花费更多的时间,你感兴趣的值不是它们的平均值,而是它能达到的最小值。但是你可以符合平均值,因为你不会进入 usec 分辨率下。
无论如何,我建议您使用 clock_gettime(2)
系统调用,因为它具有纳秒分辨率。