如何在Windows上为一个线程保留一个核心? [英] How to reserve a core for one thread on windows?

查看:114
本文介绍了如何在Windows上为一个线程保留一个核心?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个对时间非常敏感的应用程序,该应用程序轮询共享内存区域,并在检测到更改发生时采取措施.变更很少见,但我需要减少从变更到付诸行动的时间.鉴于更改的频率不高,我认为CPU缓存正在变冷.有没有办法为我的轮询线程保留一个内核,以使其不必与其他线程争用缓存或CPU?

解决方案

仅使用线程亲和力(SetThreadAffinityMask)是不够的.它不保留CPU内核,但是相反,它将线程仅绑定到您指定的内核(这是不一样的!). /p>

通过限制CPU关联性,您降低线程运行的可能性.如果另一个具有更高优先级的线程在同一内核上运行,则直到该另一个线程完成后,您的线程才会被调度(这是Windows调度线程的方式).
在不限制亲和力的情况下,您的线程有机会被迁移到另一个核心(以上次运行该线程作为该决策的度量标准).如果线程迁移经常在线程运行之后(或运行时)发生,那么迁移是不希望的,但是如果自上次调度以来已经过去了几十毫秒,这是无害的,有益的事情(缓存将被覆盖)然后无论如何).

您可以通过为它的线程赋予更高的优先级来确保"线程运行(不保证,但是可能性很高).如果随后也使用SetThreadAffinityMask,则很有可能在大多数常见的台式机CPU(幸运的是,通常是VIPT和PIPT)上,高速缓存始终处于热状态.对于TLB,您可能不会那么幸运,但是对此您无能为力.

高优先级线程的问题在于,由于实现了调度,因此它将饿死其他线程,因此它首先服务于较高优先级的类,只要不满足这些优先级,较低的类将为零.因此,在这种情况下,解决方案必须是阻止.否则,可能会对系统造成不利影响.

尝试一下:

  • 创建信号量并与其他进程共享
  • 将优先级设置为THREAD_PRIORITY_TIME_CRITICAL
  • 阻止信号量
  • 在另一个过程中,在写入数据之后,以1(甚至是零的超时)超时在信号量上调用SignalObjectAndWait
  • 如果需要,您可以尝试将它们绑定到同一核心

这将创建一个线程,该线程将是第一个(或第一个)获得CPU时间的线程,但该线程未运行. 当编写器线程调用SignalObjectAndWait时,它会自动发出信号并进行阻止(即使它等待足以重新安排时间的零时间").另一个线程将从信号量中唤醒并执行其工作.由于其较高的优先级,它不会被其他正常"(即非实时)线程中断.它将持续占用CPU时间直到完成,然后再次阻塞信号量.此时,SignalObjectAndWait返回.

I am working on a very time sensitive application which polls a region of shared memory taking action when it detects a change has occurred. Changes are rare but I need to minimize the time from change to action. Given the infrequency of changes I think the CPU cache is getting cold. Is there a way to reserve a core for my polling thread so that it does not have to compete with other threads for either cache or CPU?

解决方案

Thread affinity alone (SetThreadAffinityMask) will not be enough. It does not reserve a CPU core, but it does the opposite, it binds the thread to only the cores that you specify (that is not the same thing!).

By constraining the CPU affinity, you reduce the likelihood that your thread will run. If another thread with higher priority runs on the same core, your thread will not be scheduled until that other thread is done (this is how Windows schedules threads).
Without constraining affinity, your thread has a chance of being migrated to another core (taking the last time it was run as metric for that decision). Thread migration is undesirable if it happens often and soon after the thread has run (or while it is running) but it is a harmless, beneficial thing if a couple of dozen milliseconds have passed since it was last scheduled (caches will have been overwritten by then anyway).

You can "kind of" assure that your thread will run by giving it a higher priority class (no guarantee, but high likelihood). If you then use SetThreadAffinityMask as well, you have a reasonable chance that the cache is always warm on most common desktop CPUs (which luckily are normally VIPT and PIPT). For the TLB, you will probably be less lucky, but there's nothing you can do about it.

The problem with a high priority thread is that it will starve other threads because scheduling is implemented so it serves higher priority classes first, and as long as these are not satisfied, lower classes get zero. So, the solution in this case must be to block. Otherwise, you may impair the system in an unfavorable way.

Try this:

  • create a semaphore and share it with the other process
  • set priority to THREAD_PRIORITY_TIME_CRITICAL
  • block on the semaphore
  • in the other process, after writing data, call SignalObjectAndWait on the semaphore with a timeout of 1 (or even zero timeout)
  • if you want, you can experiment binding them both to the same core

This will create a thread that will be the first (or among the first) to get CPU time, but it is not running. When the writer thread calls SignalObjectAndWait, it atomically signals and blocks (even if it waits for "zero time" that is enough to reschedule). The other thread will wake from the Semaphore and do its work. Thanks to its high priority, it will not be interrupted by other "normal" (that is, non-realtime) threads. It will keep hogging CPU time until done, and then block again on the semaphore. At this point, SignalObjectAndWait returns.

这篇关于如何在Windows上为一个线程保留一个核心?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆