【发布时间】:2022-11-17 07:39:38
【问题描述】:
出于统计目的,我想以微秒为单位累积用于程序功能的整个 CPU 时间。它必须在两个系统中工作,一个是sizeof(clock_t) = 8 (RedHat),另一个是sizeof(clock_t) = 4 (AIX)。在两台机器中,clock_t 是有符号整数类型,CLOCKS_PER_SEC = 1000000(= 1 微秒,但我没有在代码中做这样的假设,而是使用宏)。
我所拥有的相当于这样的东西(但封装在一些花哨的类中):
typedef unsigned long long u64;
u64 accum_ticks = 0;
void f()
{
clock_t beg = clock();
work();
clock_t end = clock();
accum_ticks += (u64)(end - beg); // (1)
}
u64 elapsed_CPU_us()
{
return accum_tick * 1e+6 / CLOCKS_PER_SEC;
}
但是,在 clock_t 是 int 的 32 位 AIX 机器中,它将在 35 分钟 47 秒后溢出。假设在某些调用中,beg 等于程序启动后的 35 分钟 43 秒,而 work() 占用 10 CPU 秒,导致 end 溢出。从现在起,我可以信任(1) 电话以及随后拨打f() 电话吗?当然,f() 保证不会超过 35 分钟的执行时间。
如果即使在我的特定机器上我也根本不信任(1)行,我有什么替代方案不意味着导入任何第三方库? (我无法将库复制粘贴到系统中,也无法使用 <chrono>,因为在我们的 AIX 机器中它不可用)。
笔记:我可以使用内核标头,我需要的精度以微秒为单位。
【问题讨论】:
-
不要用 C 标记标记使用仅在 C++ 中有效的符号的问题。
-
unsigned long long类型是 C99 以来 C 的一部分,但是,是的,代码现在是有效的 C(如果您在范围内有适当的using namespace,则可能是有效的 C++)。 OTOH,除非您的问题是关于两种语言的互通,否则您仍然应该选择两种语言中的一种。 -
时钟计数器不会溢出:它像无符号一样回绕,并继续计数。
-
假设
beg = 0x7fffffff和end = 0x80000003,你得到80000003 - 0x7fffffff即4。如果您使用未签名的elapsed多变的以确保差异是正确的。或者假设beg = 0xffffffff和end = 0x0000003,你得到00000003 - 0xffffffff即4。 -
@Peregring-lk:有没有理由专门使用
clock? POSIX 提供了getrusage,它有更好的规范(clock没有指定是否包括等待子进程时间,没有指定clock_t是整数还是浮点数更不用说大小等。 ).getrusage允许您指定是否包括子进程使用的资源,分别分解用户 CPU 和系统 CPU 时间,并指定用户和系统 CPU 时间都将表示为一个结构,该结构结合了time_t秒计数具有整数微秒计数。