我想知道是否有人知道并发(即多线程,并行等)编程语言,这些编程语言的设置使得各个线程不会因为操作系统无法为它们提供CPU时间而落后于彼此。我甚至不确定装配是否可以避免这种情况。 :P但我显然不确定,因此问题。
我不是说程序需要实时访问CPU周期,我说线程不应该不同步。此外,如果语言编译为二进制可执行文件而不是字节码,或者只是由解释器运行,那将是非常好的。
答案 0 :(得分:4)
我相信没有这样的事情。
原因是如果多个线程在不同的核心上执行,那么它们只能在paralele中真正执行。事实上,在多核处理器上出现之前,技术上不可能在同一时间运行(计算)不同的线程。
现代操作系统使用大量的进程,因此使用线程(至少在进程的线程上,线程是进程的“工作”部分)。尽管是多核处理器,但在所有常见用法中,您仍然可以在系统上运行更多活动核心。
当我写这些行时,我有357个活动线程用于“仅”8个可用核心。
多数用于调度程序。它们在不同的线程之间共享可用的计算时间,以避免饥饿并给出同时执行的假象。
为了防止不同的线程同时运行并且没有时间表,你应该修改操作系统的调度程序,如果可能的话,至少是一个坏主意。
使用解释器无济于事,因为运行多线程应用程序的唯一目的是创建具有相同问题的解释线程
为了确保不同的线程被同步你应该使用barriere或信号量,因为你永远无法修改操作系统的用户计算机的调度程序
注意:在HPC应用程序中,研究人员尽量避免在上下文切换中浪费时间(保存运行线程的环境的操作以便稍后恢复)。因此,他们根据可用内核分配线程(通常他们会为操作系统和I / O留下一个内核)并将其他线程固定到特定内核。这有助于他们确保尽可能高效地完成计算。
然而,这并不能保证同步,并且仍然可能需要使用特定的mecanisme像障碍。
答案 1 :(得分:0)
使用现代处理器,确保任何特定计算以绝对已知的速率进行是非常困难的。
例如:一个采用缓存未命中的线程可能需要几百个周期,而不是具有缓存命中的相同线程。所以现在速度取决于缓存中的内容。缓存中的内容取决于线程在过去执行的复杂控制和数据流。存在许多不受控制的延迟源(管道中断,可变长度指令执行取决于操作数,OOO CPU中的内部资源争用,通过各种存储器层次结构的存储器延迟以及到其他CPU的总线,消息发送/接收时间......)
因此,要使线程以完全相同的速率运行,需要大量的控制或预知,而你几乎无法获得。 (超级计算人员几乎关闭操作系统以最大限度地减少背景噪音,例如,在随机时间发生的中断。即使这样也无济于事。)
更好的方法是让线程发出信号表明他们已经完成的工作可供另一个需要它的人使用。如果信令/等待很少发生,那么它就会被线程的计算工作所淹没,并且处理器被有效地使用。
仍然难以实现上述目标。如果你在所有CPU上进行相同的计算[例如,大数据并行计算],并且它非常规律,那么整体速率可能非常相似;你仍然需要在最后进行一些(屏障)同步,以确保它们都处于锁定状态。
很难将每个CPU上的所有计算组织为“相同”。你很可能有很多不规则(不同大小)的计算“粒子”。如果你可以跟踪那些,那么你可以在许多线程/ CPU上分配它们,依靠单个粒子之间的显式同步,使它们整体正常工作,并将新粒子交给突然空闲的CPU,这样它们就会保持忙碌状态。这可以通过“偷工作”的概念很好地完成:每个CPU都有一个可以运行的未经处理的谷物池,并且它可以尽可能快地处理它们。谷物可以制造更多的谷物(如果你用完了,你就完成了计算!)。如果CPU的谷物池变空,它会从池中窃取其他CPU的工作。工作窃取调度程序很难构建;它们必须是正确的,并避免CPU不断相互干扰,因为这只是浪费的周期。
我们的PARLANSE并行编程语言旨在处理这些问题。我们在代表程序的非常大的图表上运行它;它倾向于为图中的每个适度半径补丁生成一些工作。在这样的图表中有一百万个节点,我们需要做很多工作。