![如何调整Linux调度程序以实现并行计算?](https://linux22.com/image/185783/%E5%A6%82%E4%BD%95%E8%B0%83%E6%95%B4Linux%E8%B0%83%E5%BA%A6%E7%A8%8B%E5%BA%8F%E4%BB%A5%E5%AE%9E%E7%8E%B0%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97%EF%BC%9F.png)
我有一台专门用于运行一些并行计算的linux机器,我试图了解如何选择/调整调度程序,也许还有其他参数,以提取最大的性能(这是使用AWS部署的,所以还有一些选择使用什么 Linux 发行版,如果这很重要的话)。
我用 java 实现了计算,因为计算的不同部分之间存在一些微妙的依赖关系(总共大约有 5K 个“任务”,但一个任务通常需要在其执行过程中的多个点获取来自其他任务的信息)。我想考虑两种实现方式。
目前的实施
在当前的实现中,线程的数量等于核心的数量,每个线程都会选择一个不等待任何信息的任务,对其进行处理,直到它因某些丢失的信息而停止,此时它会丢弃该任务任务并拿起另一个任务。这一直持续到计算完成。
在这里,似乎希望每个 CPU 始终绑定到单个线程。我应该“告诉”调度程序不要执行任何时间切片,还是会自然发生?我如何确定?
另一种可能的实现
我可能会改变这一点,以便每个“任务”都有自己的线程,使用 javawait()
和notify()
范例,而不是拾取和删除计算任务。请随意评论此更改的可取性(在 96 核机器上有 5K 任务 = 线程,如果我可以加快速度,可能会更小)。但更重要的是,假设我实现了这个:
我如何告诉调度程序使用尽可能大的时间片,除非 和 调用强制wait()
要求notify()
?请问使用Java的yield()
帮助吗?
一些相关参考资料
这个答案有一些关于日程安排和参考的有用背景这和这一些更多可调参数。后者特别提到了队列争用,我在尝试扩大上面“当前实现”中的处理器数量时也注意到了这一点。
附录 这似乎是说unix(和linux?)根本没有时间片,并且线程中断的唯一方法是它被更高优先级的线程“抢占”,或者启动一些阻塞操作。事实真的如此吗?
非常感谢!
答案1
我不确定 java 中是否保证了 1:1 线程模型。这意味着 java 线程可能代表也可能不代表操作系统线程。很可能多个 Java 线程由 Java 运行时环境管理,并向操作系统表示为较少数量的线程。这确实是特定于实现的。我建议使用较低级语言(C 或 Rust)来确保 1:1 关系。
由于时间切片对您很重要,我还建议选择实时优先级setpriority()
这使您可以访问一些有趣的调度策略。如果您想避免时间切片,请使用该SCHED_FIFO
策略。这将确保线程在完成之前不会被中断,除非更高优先级的线程已排队。如果所有 5k 线程都具有相同的优先级,那么它实际上是一个具有最少上下文切换的先进先出解决方案。看sched(7)
了解详情。
您的线程将不会被中断,直到它们完成或调用read()
在代表互斥锁的 FD 或代表跨线程通信何时准备好读取的其他文件上。此时您的线程将被阻塞,而另一个线程有机会运行。
因此我认为你的想法是使用 5k 线程并简单地对它们进行排队是一个好主意。
一个陷阱与内核有关-rt
。这提供了抢占式调度,以牺牲性能为代价(提前清除CPU队列)来提高线程唤醒时间的精度。对于如此低级的问题,我假设您正在尝试最大限度地提高性能,因此这对您不起作用。