我已经开始使用并发性来使用Scala创建一个物理引擎。 我知道很多数字运算可以并行化(这对于事物的优化很重要)。
但是我知道使用actor或futures进行并行性的抽象会带来很多开销。我真正应该多久使用一次期货和演员?我可以想象使每个数字语句(例如factorial(4)
或gcd(5,10)
)成为未来可能会使事情变得效率低下,因为您现在要在多个层次上并且经常为这些开销付费。
也许在scala中有更好的方法可以并行化较低级别的执行?您对期货和参与者的使用频率有何看法?
答案 0 :(得分:3)
我认为有必要区分真正的并行性和更广泛的并发性。
并行性是一种通过同时执行多个计算来使您的代码运行更快的方法。范围从CPU上的SIMD指令到多个服务器上的分布式应用程序。并行性的选择取决于问题的性质。
并发性是一种通过将代码分为似乎同时执行的不同部分来实现separation of concerns的方法。主要目标是允许应用程序即使在单个线程上执行,也可以处理多个任务。
演员和未来主要用于实现并发。参与者在整个系统中扮演特定角色,并且似乎独立且异步地进行操作,从而使人们更容易推断出系统那部分的行为。期货是一种逃避严格的线性执行的方式,它说某项操作将在未来某个不确定的时间发生。
Scala并不真正支持SIMD指令(可能是由于JVM基础),但是有一些GPU加速库,如果要进行重量级计算,则一定要看一下。
可以使用Scala中的 parallel collection 类完成简单的任务级并行操作,这可能会有效地使用多个线程。
可以使用期货来生成任务以并行执行,但是它们缺乏对调度的控制(它们会立即启动),因此最好使用Scala任务库之一。
您可以使用actor进行线程级并行处理,其中在应用程序执行期间将多次执行相同的计算。计算被包装在一个actor中,然后将该actor复制到多个线程,核心或处理器上。每次计算都由发给参与者的消息触发,然后使用第二条消息将结果返回到主应用程序。这对于长时间运行具有少量输入和输出数据的计算很有用,但是,如果数据过多,则在进程之间移动数据的开销可能会成为很大的开销。
当然,有多种方法可以在多个服务器之间分配代码,参与者是这种方法的理想选择。此时,移动数据已成为关键问题。