【发布时间】:2014-10-24 19:45:41
【问题描述】:
我正在编写一个使用第三方库来执行繁重计算的应用程序。
这个库在内部实现并行性并产生给定数量的线程。我想运行这个库的几个(动态计数)实例,因此最终会严重超额订阅 cpu。
有什么方法可以增加进程中所有线程的“时间量子”,例如所有具有正常优先级的线程很少上下文切换(yield),除非它们通过例如明确地让出。信号量?
这样我可以避免过度订阅 CPU 的大部分性能开销。请注意,在这种情况下,我不在乎线程是否饿了几秒钟。
编辑:
一种复杂的方法是手动执行线程调度。
- 枚举具有特定优先级(例如正常)的所有线程。
- 暂停所有这些。
- 创建一个循环来恢复/暂停线程,例如40 毫秒,并确保运行的线程数不超过当前 cpu 计数。
这种方法有什么主要缺点吗?不确定恢复/暂停线程的开销是多少?
【问题讨论】:
-
lib 实例是否相互依赖?如果不是,为什么不能通过以线程池的方式运行与内核一样多的线程来避免可用内核过载?
-
好吧,因为实例的数量是动态变化的,这很困难。我需要多次初始化/重新初始化库以根据当前负载更改线程数。
-
如果你使用了线程池,任何时候运行的库实例的数量将与池中的线程数相同。其他库实例只会排队等待池线程可用于处理它们。如果结果超载,将 CPU 应用于实例似乎没有意义?
-
如果是windows,也许您可以通过使用timeBeginPeriod() 和timeEndPeriod() 将ticker 设置为更高的值来降低tick rate。我认为默认是 15.625 毫秒(64 赫兹)。
-
如果你有 8 个核心,启动 8 个线程。 8 个线程从阻塞队列中弹出库实例,并在它们可用时对其进行处理。如果排队的实例超过 8 个,则处理 8 个,其余的排队。当一个线程完成运行一个实例时,它会循环回来尝试从队列中弹出另一个实例。由于总是只有 8 个线程,因此无论有多少实例提交到队列,都不会出现过载。
标签: c++ c multithreading winapi context-switch