Scala Parallel Mergesort - 内存不足

时间:2013-03-23 16:59:35

标签: scala concurrency parallel-processing future

我尝试使用Scala Futures编写并行Mergesort。但是,当我在Eclipse的解释器中运行我的算法大小为100 000的列表时,一切都变得非常缓慢,最终我收到一条错误消息,告诉我我的内存不足。当我从命令行在解释器中运行它时,它已挂起大小为10 000的列表(但现在我没有收到任何错误消息)。

为什么会发生这种情况并且有解决方法?

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)
    }
}

2 个答案:

答案 0 :(得分:2)

你应该尝试使用Akka未来并根据你的需要调整ExecutionContext:

看起来std-lib没有为你提供类似用例的默认值。

答案 1 :(得分:0)

正如Rex指出的那样,(任何)Future 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中实现了并行外部合并排序。我在我的博客上解释了实施细节:http://blog.yunglinho.com/blog/2013/03/19/parallel-external-merge-sort/