我正在编写一个CPU密集型图像处理库。为了充分利用可用的CPU,我可以检测机器上的核心总数,并让我的库运行该线程数。当我的库为每个核分配一个线程时,它使用100%可用的处理器时间以最佳方式执行。
当我的运行中唯一占用CPU的进程时,上述方法可以正常工作。如果正在运行另一个CPU密集型进程,或者甚至是我自己代码的另一个实例,那么操作系统只会为我们分配一小部分可用内核,然后我的库会运行太多线程,这对其他进程来说既低效又无意义。 / p>
所以我想找到一种方法来确定在特定负载下运行的“公平共享”线程数。例如,如果我的进程的两个实例在8核计算机上运行,则每个实例将运行4个线程。每个都需要一种方法来根据机器负载的波动动态调整线程数。
所以,我的问题:
我的重点是Windows,但也对非Windows解决方案感兴趣。
编辑:要明确,这是关于优化。我试图通过运行适合我公平份额的CPU的最佳线程数来实现最高效率。
答案 0 :(得分:1)
在我看来,应用程序不应该决定产生多少线程。这是呼叫者应该知道的信息。在linux中,广泛使用“-j”或“--jobs”参数(默认值:1)。
如何设置处理任务的优先级。因此,如果调用者知道,处理是关键任务,他可以增加prio(知道可能阻塞(整个)系统)。您的处理库永远不会知道此图像的处理有多重要。 如果调用者不关心,则使用默认的低prio,不应影响系统的其余部分。如果是这样,你应该看看究竟是什么阻塞了系统(可能是将图像文件写入hdd,减少ram大小以防止交换,......)。如果你弄清楚了,你可以准确地优化这一点。
如果在低到正常优先级的情况下使用(cpu-cores)* 2开始处理,则系统应该可用。没有人会想到,这会杀死系统。
只需2美分。
答案 1 :(得分:1)
实际上,这不是多线程的问题,而是同时执行多个程序的问题。这在大多数PC的操作系统上都很难,因为它与分时的想法相冲突。
我们假设一些工作流程。
假设我们有8个核心,我们创建8个线程来提供它们;好的,这很容易。接下来,我们选择监控核心负载,以总结在某个核心上运行的任务数量;好吧,这需要一些统计假设,例如在Linux上你可以获得1/5/15分钟的平均负载图表,但这可以做到。统计图表很清楚,现在我们得到一个关于运行多少CPU绑定进程的图表,比如看到其他3个CPU密集型进程。
然后我们来到这一点:我们必须让3个冗余线程休眠,但是哪个3?
通常我们任意选择3个线程,因为调度程序会自动排列其他8个CPU绑定线程。在某些情况下,我们明确地将高负载核心上的线程置于休眠状态,将其他线程分配给某些低负载核心,并让调度程序执行其余操作。大多数调度策略也尝试“保持CPU缓存热”,这意味着他们倾向于禁止在核心之间传输线程。我们合理地期望我们的CPU密集型线程可以利用核心缓存,因为其他进程被安排到3个拥挤的核心。一切都很好看。
然而,在紧密同步的计算中,这可能会失败。在这种情况下,我们需要同时运行我们的5个线程。同时在这里意味着5个线程必须获得CPU并几乎同时运行。我不知道PC上是否有任何调度程序可以为我们这样做。在大多数低负载情况下,事情仍然可以正常工作,因为等待同时性的成本是微不足道的。但是当一个核心的负载很高,甚至我们的5个线程中的一个被扰乱时,偶尔我们会发现我们在等待中花费了很多生命周期。
将您的程序安排为实时程序可能会有所帮助,但这不是一个完美的解决方案。从统计上来说,当它获得更多CPU控制优先级时,它会导致同时具有更宽的时间窗口。我不得不说,这不能保证。