Scala并行合并内存排序

Scala并行合并内存排序,scala,concurrency,parallel-processing,future,Scala,Concurrency,Parallel Processing,Future,我尝试使用Scala Futures编写一个并行合并排序。然而,当我在Eclipse的解释器中对大小为100000的列表运行我的算法时,一切都变得非常缓慢,最终我收到一条错误消息,告诉我内存不足。当我从命令行在解释器中运行它时,它已经挂起了大小为10000的列表(但现在我没有收到错误消息) 为什么会发生这种情况,有解决办法吗 import scala.actors.Future import scala.actors.Futures._ object MergeSort{ def so

我尝试使用Scala Futures编写一个并行合并排序。然而,当我在Eclipse的解释器中对大小为100000的列表运行我的算法时,一切都变得非常缓慢,最终我收到一条错误消息,告诉我内存不足。当我从命令行在解释器中运行它时,它已经挂起了大小为10000的列表(但现在我没有收到错误消息)

为什么会发生这种情况,有解决办法吗

import scala.actors.Future
import scala.actors.Futures._

object MergeSort{
    def sort[T <% Ordered[T]](toBeSorted :List[T]) :List[T] = toBeSorted match{
      case Nil => Nil
      case List(x) => List(x)
      case someList =>
        val (left, right) = someList splitAt someList.length/2
        val sortedLeft = future { sort(left) }
        val sortedRight = sort(right)
        merge(sortedLeft(), sortedRight, Nil)
    }

    def merge[T <% Ordered[T]](a :List[T], b :List[T], Ack: List[T]) :List[T] = (a, b) match {
      case (Nil, ys) => Ack.reverse ++ ys
      case (xs, Nil) => Ack.reverse ++ xs
      case (x::xs, y::ys) if x < y => merge(xs, y::ys, x::Ack)
      case (x::xs, y::ys) => merge(x::xs, ys, y::Ack)
    }
}
导入scala.actors.Future
导入scala.actors.Futures_
对象合并排序{
def sort[T Nil
案例列表(x)=>列表(x)
case-someList=>
val(左、右)=someList拆分为someList.length/2
val sortedLeft=未来{sort(左)}
val sortedRight=排序(右)
合并(sortedLeft(),sortedRight,无)
}
def合并[T Ack.reverse++ys
大小写(xs,Nil)=>Ack.reverse++xs
如果xmerge(xs,y::ys,x::Ack),则为case(x::xs,y::ys)
案例(x::xs,y::ys)=>merge(x::xs,ys,y::Ack)
}
}

您应该尝试使用Akka future,并根据需要调整ExecutionContext:


看起来std库并没有为这样的用例提供良好的默认值。

正如Rex指出的,未来API的开销是相当大的,不应被忽略

不要在上下文切换开销上浪费宝贵的cpu和内存。你应该将列表分成大小合理的块,并在同一线程中执行排序

例如,如果您的计算机上有4个内核和4GB内存,您可以将其拆分为500MB块,并同时运行多达4个合并排序。这将最大限度地提高吞吐量和并行性

您可以使用SIP-14的ExecutionContext来限制使用的线程数

private val GLOBAL_THREAD_LIMIT = Runtime.getRuntime.availableProcessors()
private lazy implicit val executionContext =
   ExecutionContext.fromExecutorService(
       Executors.newFixedThreadPool(GLOBAL_THREAD_LIMIT)
)

顺便说一句,我在SIP-14中实现了一个并行外部合并排序。我在我的博客上解释了实现细节:

仅供参考,这种并行合并排序将比任何普通的合并排序都要慢,除非你有一个非常慢的比较函数,因为创建未来的开销远远大于比较两个项目。这也是为什么Eclipse等会扼杀它。