草庐IT

windows - Windows 10 下多核处理器上的 QueryPerformanceCounter 行为不稳定

coder 2024-06-05 原文

在 Windows 下,我的应用程序使用 QueryPerformanceCounter(和 QueryPerformanceFrequency)来执行“高分辨率”时间戳。

自 Windows 10 以来(目前仅在 Intel i7 处理器上进行了测试),我们观察到 QueryPerformanceCounter 返回值的不稳定行为。 有时,调用返回的值会跳得很远,然后又回到它以前的值。 感觉好像线程已经从一个核心移动到另一个核心,并且在一段时间内返回了不同的计数器值(没有证据,只是一种直觉)。

这在 XP 或 7 下从未观察到(没有有关 Vista、8 或 8.1 的数据)。

一个“简单”的解决方法是使用 BCDEdit 启用 UsePlatformClock 引导选项(这使得一切都正常运行)。

我知道可能更高级的 GetSystemTimePreciseAsFileTime,但由于我们仍然支持 7,所以这不是一个确切的选择,除非我们为不同的操作系统编写完全不同的代码,而我们真的不想这样做。

在 Windows 10 下是否观察到/解释了此类行为?

最佳答案

我需要更多关于您的代码的知识,但让我强调一些来自 MSDN 的内容:

When computing deltas, the values [from QueryPerformanceCounter] should be clamped to ensure that any bugs in the timing values do not cause crashes or unstable time-related computations.

尤其是这个:

Set that single thread to remain on a single processor by using the Windows API SetThreadAffinityMask ... While QueryPerformanceCounter and QueryPerformanceFrequency typically adjust for multiple processors, bugs in the BIOS or drivers may result in these routines returning different values as the thread moves from one processor to another. So, it's best to keep the thread on a single processor.

您的案例可能利用了其中一个错误。简而言之:

  • 您应该始终从一个线程查询时间戳(设置相同的 CPU 亲和性以确保它不会更改)并从任何其他线程读取该值(只是互锁读取,不需要花哨的同步)。
  • 限制计算出的增量(至少要确保它不是负数)...

注意事项:

QueryPerformanceCounter() 如果可能,使用 TSC(参见 MSDN )。同步 TSC 的算法(如果可用,在您的情况下应该是)从 Windows 7 到 Windows 8 发生了巨大变化,但请注意:

With the advent of multi-core/hyper-threaded CPUs, systems with multiple CPUs, and hibernating operating systems, the TSC cannot be relied upon to provide accurate results — unless great care is taken to correct the possible flaws: rate of tick and whether all cores (processors) have identical values in their time-keeping registers. There is no promise that the timestamp counters of multiple CPUs on a single motherboard will be synchronized. Therefore, a program can get reliable results only by limiting itself to run on one specific CPU.

然后,即使理论上 QPC 是单调的,您也必须始终从同一个线程调用它以确保这一点。

另一个注意事项:如果同步是由软件进行的,您可以从 Intel 文档中读到:

...It may be difficult for software to do this in a way than ensures that all logical processors will have the same value for the TSC at a given point in time...


编辑:如果您的应用程序是多线程的并且您不能(或者您不想)设置 CPU 亲和性(特别是如果您需要精确的时间戳,但代价是去-线程之间的同步值),那么您可以在 Win8(或更高版本)上运行时使用 GetSystemTimePreciseAsFileTime() 并回退到 Win7 的 timeGetTime()(将粒度设置为 1 毫秒后使用 timeBeginPeriod(1) 并假设 1 毫秒的分辨率就足够了)。一个非常有趣的阅读:The Windows Timestamp Project .

编辑 2:OP 直接建议!这在适用时(因为它是系统设置,而不是您的应用程序的本地设置)可能是一个简单的解决方法。您可以使用 bcdedit(参见 MSDN)强制 QPC 使用 HPET 而不是 TSC。延迟和分辨率应该更差,但本质上安全不会出现上述问题。

关于windows - Windows 10 下多核处理器上的 QueryPerformanceCounter 行为不稳定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44020619/

有关windows - Windows 10 下多核处理器上的 QueryPerformanceCounter 行为不稳定的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  3. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  4. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  5. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  6. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  7. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  8. ruby-on-rails - Ruby - 如何从 ruby​​ 上的 .pfx 文件中提取公钥、rsa 私钥和 CA key - 2

    我有一个.pfx格式的证书,我需要使用ruby​​提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o

  9. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

  10. 带有 attr_accessor 的类上的 Ruby instance_eval - 2

    我了解instance_eval和class_eval之间的基本区别。我在玩弄时发现的是一些涉及attr_accessor的奇怪东西。这是一个例子:A=Class.newA.class_eval{attr_accessor:x}a=A.newa.x="x"a.x=>"x"#...expectedA.instance_eval{attr_accessor:y}A.y="y"=>NoMethodError:undefinedmethod`y='forA:Classa.y="y"=>"y"#WHATTT?这是怎么回事:instance_eval没有访问我们的A类(对象)然后它实际上将它添加到

随机推荐