具有直接 QueryPerformanceCounter 值的时钟可以符合 C++ 标准吗?

Posted

技术标签:

【中文标题】具有直接 QueryPerformanceCounter 值的时钟可以符合 C++ 标准吗?【英文标题】:Can Clock with direct QueryPerformanceCounter value be conforming to C++ Standard? 【发布时间】:2020-03-27 12:50:39 【问题描述】:

假设我想用直接的QueryPerformanceCounter Windows API 结果创建ClockQueryPerformanceCounter Windows API 返回一些计数器,该计数器应除以 QueryPerformanceFrequency 结果,从而产生以秒为单位的时间。

通常基于QueryPerformanceCounterClock 会立即通过乘以某个句点并除以QueryPerformanceFrequency 将结果转换为某些单位。这就是 steady_clock 在 Windows 上的实现方式。

但假设出于性能原因,我想在真正需要之前避免分裂。所以time_point是直接QueryPerformanceCounter的值,而duration是这样的区别。而且我大部分时间都可以对这些值进行算术和比较,仅将最终结果转换为一些正常的durationtime_point

我相信这是可能的。我的问题是:这样的Clock 会完全兼容标准的Clock

【问题讨论】:

你的意思是named requirement Clock? 是的,时钟命名要求 据我了解,Clock 的唯一要求是@idclev463035818 已经解释过的......所以Clock 的概念就是满足这个要求。时间点可以是你想要的任何东西,它只需要表示从 epoch 传递了多少滴答声 我并没有真正解释它,但上面的链接确实列出了满足要求所需的所有内容,不是专家,但 afaik 它只是提供某些方法而不是is_steady对语义的要求比较宽松 ...所以,要回答您的问题,您必须出示您的代码。 【参考方案1】:

它不会与标准Clock Requirements 完全兼容。但它会编译并做你想做的事,大多数时候。不符合的部分是您必须为time_point 所基于的period 指定something。而且这不一定与物理时间单位相对应。

这无关紧要,除非您减去其中两个 time_points,得到 duration,然后将 duration确实代表物理时间的东西进行比较。然后你会得到运行时垃圾。

此外,如果您在sleep_untilwait_until 中使用这样的time_point,那么您的程序将不会休眠或等待预期的时间。

这是一个基于QueryPerformanceCounter 的计时时钟示例,它使用QueryPerformanceFrequency 确定物理单位:https://***.com/a/15755865/576911

【讨论】:

感谢您的回答。我正在考虑使period 完全合法的纳秒周期,但在rep 类型中隐藏系统特定的单元,因为它可能是a class emulating an arithmetic type。还是不行吗? 所以当您的自定义rep 转换为标量时会发生物理时间的转换?可能会奏效。不确定。 我自己研究过这个问题,不,自定义rep 不起作用。但我原来的问题有解决方案。我已经添加了自己的答案。【参考方案2】:

正如 Howard Hinnant 解释的那样,重新定义的 time_pointduration 与编译时已知的 period 不对应的时钟不符合 Clock 要求。


使用模拟算术类型的类来隐藏额外的实现细节是行不通的。

由于标准没有定义什么是仿真,使用仿真类型的机会仅适用于标准实现提供的时钟。作为一个实践证明,std::chronoboost::chrono 不能很好地与 boost::rational 配合使用。


然而,避免在每次查询中分割的一般任务至少有两个实际的解决方案。

第一个解决方案是遵循延迟除法直到需要的意图,但不重新定义time_pointduration。定义符合标准的时钟,并作为扩展定义原始时间戳的接口。所以,clock 可能有raw_now() 方法,返回raw_time_point 类型,这样的区别是raw_duration 类型。 raw_time_point 可以隐式转换为 time_pointraw_durationduration


第二种解决方案是为每次查询计算符合标准的time_point,但使用libdivide 库进行快速除法而不进行除法运算。

该库采用除数并对其进行处理,以便使用已处理除数的每个除法都使用快速操作完成。当然,处理除数需要时间,但对于相同除数的重复除法,它是一次性开销。所以这个库看起来是这个任务的理想匹配。 (请注意,该库对于编译时已知的常量没有用,因为在这种情况下编译器会避免自行除法,但QueryPerformanceFrequency 结果是运行时常量)。

【讨论】:

以上是关于具有直接 QueryPerformanceCounter 值的时钟可以符合 C++ 标准吗?的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP中具有直接多态关联的MySQL错误

直接从表中选择和从视图中选择是不是具有相同的性能影响

Pod具有未绑定的直接PersistentVolumeClaims

Google Pub/Sub 功能是不是具有在上传后直接通知 Google App Engine 端点的某些功能?

使用 Tableau 或 PowerBI 直接查询具有 1b 行数据的数据库

我可以直接从具有特定大小类或特征集合的 xib 加载 UITableViewCell 吗?