Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当前线程的线程关联掩码更改有什么好处?_C++_Winapi_Setthreadaffinitymask_Performancecounter - Fatal编程技术网

C++ 当前线程的线程关联掩码更改有什么好处?

C++ 当前线程的线程关联掩码更改有什么好处?,c++,winapi,setthreadaffinitymask,performancecounter,C++,Winapi,Setthreadaffinitymask,Performancecounter,我正在编写一个游戏引擎,我需要一种方法来获得一个精确的“deltatime”值,从中可以导出用于调试的当前FPS,并限制帧速率(这对我们的项目很重要) 通过一些研究,我发现最好的方法之一是使用WinAPI的QueryPerformanceCounter函数GetTicksCount来防止,但它本身并不十分准确 现在,QueryPerformanceCounter的问题在于,它显然可能返回的值与时间向后弯曲时的值类似(即,一个调用可能返回的值在时间上比过去的另一个调用早)。只有当一个给定的处理器内

我正在编写一个游戏引擎,我需要一种方法来获得一个精确的“deltatime”值,从中可以导出用于调试的当前FPS,并限制帧速率(这对我们的项目很重要)

通过一些研究,我发现最好的方法之一是使用WinAPI的
QueryPerformanceCounter
函数<必须使用code>GetTicksCount来防止,但它本身并不十分准确

现在,
QueryPerformanceCounter
的问题在于,它显然可能返回的值与时间向后弯曲时的值类似(即,一个调用可能返回的值在时间上比过去的另一个调用早)。只有当一个给定的处理器内核获得的值与另一个处理器内核获得的值进行比较时,才会出现这种情况,这就引出了促使我发表这篇文章的终极问题:

  • 当线程已经运行时,操作系统是否可以将线程“重新分配”到另一个内核,或者是否将线程分配给给定的内核,直到线程死亡
  • 如果一个线程不能被重新分配(至少这对我来说很有意义),那么为什么我可以做类似于
    SetThreadAffinityMask(GetCurrentThread(),mask)
    ?我想这是为了避免时间倒流。但是,如果是这样的话,我将不得不考虑线程被OS从任意一个内核移动到另一个内核的可能性,这对我来说似乎很奇怪(不知道为什么)。 我想现在我只想知道这些。谢谢。

    在线程运行时,线程可以重新分配,也可以重新分配(除非它们具有关联集)。Windows将负载分散到所有处理器上,以最大限度地提高性能。

    1)线程可以将线程分配给任何有空闲处理时间的内核。这就是为什么你会经常看到软件在四核机器上使用50%,而当你检查图表时,它使用了所有四个的一半


    2) 见第1条;)

    使用SetThreadAffinity()通常是个坏主意,除非线程只进行计时。如果将线程锁定到一个单核,那么首先就失去了拥有多核系统的所有好处。您的应用程序无法再扩展。即使您启动应用程序的多个实例,它们仍将锁定到单个核心。

    除非某个线程具有处理器关联掩码,否则调度程序会将其从一个处理器移动到另一个处理器,以便为其提供执行时间。因为在处理器之间移动线程会降低性能,所以它会尝试不移动线程,但给它一个处理器来执行线程比不移动线程具有更高的优先级。所以,通常线程会移动

    至于计时器API。是为多媒体计时而设计的,因此它比
    GetTickCount
    更精确

    QueryPerformanceCounter()。
    仍然是您最精确的度量。微软对此有这样的说法

    在多处理器计算机上,调用哪个处理器并不重要。但是,由于基本输入/输出系统(BIOS)或硬件抽象层(HAL)中的错误,您可以在不同的处理器上获得不同的结果。要为线程指定处理器亲缘关系,请使用SetThreadAffinityMask函数


    因此,如果你在一台特定的计算机上进行计时测试,你可能不必担心QPC会倒退,你应该做一些测试,看看它在你的机器上是否重要。

    即使你使用SetAffinityMask将线程锁定到一个处理器上,如果你真的不走运并且硬件很糟糕,QPC也会倒退运行。最好只处理QPC返回错误值的情况。在Windows7中,QPC在这方面有了显著的改进,但由于您正在编写一个游戏,您可能将目标锁定在XP上,而XP对您没有帮助


    另外,不要设置线程关联,您可能会使自己死锁,引入奇怪的计时和性能错误,并且通常会让自己感到悲伤

    因此,在运行计时时,我们通常必须将游戏锁定在单个线程中;我们没有找到有效的解决方法,因为在测量性能时需要亚微秒的分辨率

    有一件事让它变得更容易一些,那就是我们的引擎被分成了广泛的组件,这些组件总是并发运行(例如游戏/逻辑“服务器”、输入/图形“客户端”、音频、渲染都是它们自己的线程),所以我们要做的是将这些线程锁定到自己的核心上,并独立计时


    类似地,因为我们知道渲染循环总是在核心0上,所以我们使用它来计时帧速率。

    因此,从您可以看出,如果不将关联掩码设置为仅一个核心,并且使用QueryFrequencyCounter,那么当从不同的核心调用函数时,计数器确实会扭曲回去。是吗?在交换核心时,时间可能会倒流,是的。好吧,我想这就解决了。我必须创建一个线程来测量时间,并使用互斥体来查询时间,这样测量总是只在一个线程中发生,对吗?类似的情况。不要忘记,互斥体/关键部分涉及从用户模式切换到内核模式,因此它们会受到速度的影响。为什么有人会启动一个游戏的多个实例?谁知道呢。也许应用程序的各个部分被分解成不同的应用程序。更重要的是,这有什么关系?@Crashworks没有人会,但他确实有道理。这就是为什么我没有先问一下,就没有继续建立亲密关系。我还认为,这应该只是为了时间安排。很高兴听到有人像我一样思考。因为他们想对一个游戏的多个实例做些什么?比如说,无论出于何种原因,在本地测试网络游戏时,这并非闻所未闻。FWIW,我们的经验是,我们引擎的各个组件对时间非常敏感,因此我们必须为每个组件设置明确的亲缘关系