多核使用、线程、线程池
我有一些关于多线程编程和多核使用的问题。
我特别想知道操作系统和/或框架(这是.NET)如何处理频繁使用的核心。
这是我关于线程的问题:
- 当生成新线程时,将线程分配给特定核心的算法是什么?
- 循环类型的算法
- 随机
- 当前最少使用的核心
- 如果不是当前最少使用的核心,那么确定此类型的代码是否会使线程的典型使用相形见绌,从而使事情变得更糟?
- 线程在其生命周期内是否从一个核心移至另一个核心? 如果是这样,这是否是为了处理由于某种原因“过度使用”的核心,因此操作系统尝试将线程转移到较少使用的核心以帮助系统? 如果不是的话,为什么不呢?
我的最后一个问题基本上是上述问题的重用,是关于 .NET ThreadPool 类的,它处理 .BeginInvoke 等内容。 这个类有做这些事情吗? 如果没有,为什么不或者应该这样做?
有没有什么方法可以调整这个处理,有点向操作系统暗示这个特定的线程,当你给它分配一个核心时请多加注意,因为我知道它会使用大量的CPU。 这有意义吗? 或者“大量CPU”只是相对的,因此还不够好?
I have some questions about multi-threaded programming and multi-core usage.
In particular I'm wondering how the operating system and/or framework (this is .NET) deals with cores that are heavily used.
Here's my questions regarding threads:
- When a new thread is spawned, what is the algorithm for assigning the thread to a particular core?
- Round-robin type of algorithm
- Random
- The currently least used core
- If not the currently least used core, would this type of code that determined this dwarf the typical use of a thread and thus just make matters worse?
- Are threads moved from one core to another during their lifetime? If so, is this to handle cores that for some reason gets "overused" and thus the operating system try to shuffle threads over to less used cores to help the system? If not, again, why not?
My final question, which is basically a reuse of the above, is about the .NET ThreadPool class, which handles things like .BeginInvoke and such. Does this class do any of this stuff? If not, why not, or should it?
Is there any way to tweak this handling, sort of hint at the operating system that this particular thread, please pay a bit more attention to it when you assign it a core, since I know it will use a lot of cpu. Would that make sense? Or would "a lot of cpu" just be relative and thus not really good enough?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这完全取决于操作系统。 答案通常是经过大量修改的循环方案。 每x毫秒,一个核心被中断,并在其上放置一个新线程(因此不存在“最少使用的核心”。只要有线程准备运行,每个核心都会有事情要做)。
在 Windows 中,我相信优先级最高的线程/进程总是被选择执行。 (因此,如果您有一个进程在单核系统上以高优先级运行,则该进程可能会在 100% 的时间内运行,从而导致其他所有进程都处于饥饿状态。当然,这仅适用于该进程从不阻塞的情况,而这在 。
当然,由于 Windows 等现代操作系统非常复杂,因此某些进程有时会受到优先处理,但根据经验,Windows 总是会选择高优先级 进程(这就是为什么在单核时代,你可以通过给进程“实时”优先级来几乎冻结你的计算机)
在Linux下,优先级较低的进程也会被定期调度,只是频率不那么高,
但这是你能做的最好的事情。通常只是假设操作系统会制定一个公平的方案,然后尝试与系统的其余部分很好地合作(当你无事可做时,让出/阻塞/睡眠,允许其他线程运行)。
当然。 想象一下,您在双核系统上运行三个线程。 向我展示一个公平的时间表,不涉及定期在核心之间移动线程。
这就是线程/进程优先级的用途。 如果您有一个线程必须获得大量 CPU 时间,即使有其他 CPU 密集型线程正在运行,也请提高该线程的优先级。
但要小心处理。 通常,运行的 CPU 密集型线程并不多,这意味着即使在正常优先级下,您也将获得 99.9% 的 CPU 时间。 正如我所说,Windows 会非常积极地调度优先级较高的线程,因此只有在您确实这么想时才提高优先级。
That depends entirely on the OS. And the answer is usually a heavily modified round-robin scheme. Every x milliseconds, a core is interrupted, and a new thread placed on it (so there is no "least used core". As long as there are threads ready to run, every core will have something to do).
In Windows, I believe the highest-prioritized thread/process is always selected for execution. (So if you have one process running at high priority on a single-core system, that process will potentially run 100% of the time, starving out every other process. Of course this only applies if that process never blocks, which is unlikely in the real world.
And of course, because a modern OS such as Windows is complex, there's a lot more to it. Certain processes are given preferential treatment from time to time, but as a rule of thumb, Windows will always pick high-priority processes (which is why you could pretty much freeze your computer by giving a process "realtime" priority back in the singlecore days)
Under Linux, lower-prioritized processes are regularly scheduled as well, just not as often.
But the best you can do is typically just assume that the OS will work out a fair scheme, and then try to play nice with the rest of the system. (Yield/block/sleep when you have nothing to do, allowing other threads to run).
Of course. Imagine you have three threads running on a dualcore system. Show me a fair schedule that doesn't involve regularly moving threads between cores.
That's what thread/process priority is for. If you have a thread that must get lots of CPU time, even when there are other CPU-intensive threads running, raise the thread's priority.
But handle with care. Usually, there aren't many CPU-intensive threads running, which means that even at normal priority, you'll get 99.9% of the CPU time. As I said, Windows schedules higher-prioritized threads very aggressively, so only raise priority if you really mean it.
除了 jalf 出色且全面的答案之外,请记住“并行扩展”(应纳入 .NET 4.0)有大量代码专门用于将工作(从队列)均匀分配到内核,包括工作窃取,以及潜在的金块,例如关心哪个核心与工作所在的内存“最接近”。
因此,在 .NET 4.0 中,使用 Parallel.For 等,您应该可以免费获得很多这样的功能。 一般来说,操作系统足够聪明,从局外人的角度来看它只是工作。 jalf 提供了有关幕后发生的情况的大量详细信息,但大多数时候您不需要这种级别的详细信息,除非您正在解决高度线程代码的一些性能问题。
In addition to jalf's excellent and comprehensive answer, keep in mind that "Parallel Extensions" (which should be rolled into .NET 4.0) has a lot of code dedicated to allocating work (from queues) to cores evenly, including work stealing, and potentially nuggets like caring which core is "closest" to the memory in which the work resides.
So with .NET 4.0, using things like
Parallel.For
etc, you should get a lot of this for free. And in general, the OS is clever enough that it just works from the outsider's view. jalf has given a lot of details about what happens under the hood, but most of the time you don't need this level of detail, unless you are ironing out some performance issues with highly threaded code.