【问题标题】:Why is this multi-threaded bubble sort taking so long?为什么这种多线程冒泡排序需要这么长时间?
【发布时间】:2019-08-12 00:43:48
【问题描述】:

我正在尝试为家庭作业问题实现更有效的冒泡排序,这需要我们创建一个包含 3,000,000 个随机双精度数的列表,并使用多线程将列表分成四个季度,同时每个季度进行冒泡排序。每个季度(750,000 个数字)应该需要大约 7 分钟,但在我的计算机上,即使对 10,000 个双精度数(每季度 2,500 个)进行排序也需要大约 6 分钟,并且一个多小时后还没有完成对 1,000,000 个整数列表的排序。我正在使用 2012 Macbook Pro。有没有人知道为什么这个程序需要这么长时间?

import scala.util.Random
import scala.collection.mutable.ListBuffer

object bubbleSortTest extends App{
  val size:Int = 10000
  val numDivs:Int = 4
  val list = ListBuffer.fill(size)(Random.nextDouble*100) 
//create list of 10000 random doubles

  val divs = ListBuffer[ListBuffer[Double]]()
  for(i <- 0 until numDivs) 
    divs += list.grouped(list.length/numDivs).toList(i).to[ListBuffer]
//divide list into quarters and put quarters into new list divs

  val s0 = new Sorter("s0",list) 
//create sorter for entire list
  val sorters = divs.zipWithIndex.map(x => new Sorter(s"s${x._2 + 1}", x._1)) //create sorter for each quarter

  s0.start()
  for(s <- sorters)
    s.start()

}

class Sorter(name:String, list:ListBuffer[Double]) extends Thread {

  override def run() {
    val t0 = System.nanoTime()
    sort(list)
    val t1 = System.nanoTime()
    println(s"$name done: ${(t1-t0)/1e9}s")
    //println(list)
  }

  def sort(list:ListBuffer[Double]): List[Double] = {
    var didSwap = false
    for(i <- 0 until list.length-1) {
      //println(s"$getName: $i")
      if(list(i)>list(i+1)) {
        didSwap = true
        var temp = list(i)
        list(i) = list(i+1)
        list(i+1) = temp
      }
    }

    if(didSwap)
      return sort(list)
    else
      return list.toList
  }
}

【问题讨论】:

    标签: multithreading scala sorting bubble-sort


    【解决方案1】:

    这可能是因为您正在使用 ListBuffer。链表有一个潜在问题,即遍历链表期间的每个单独步骤都可能导致缓存未命中。尝试其他可变数据结构,例如 Array 或 ArrayBuffer。因为 Array 或 ArrayBuffer 中的连续槽在内存中并排存在,所以缓存未命中的情况会更少,这意味着您的排序应该更快。

    【讨论】:

      【解决方案2】:

      问题在于ListBuffer 是一个列表而不是一个数组,列表中的每个元素都指向下一个元素,而不是位于单个内存块中。这意味着采用lengthlength 意味着计算列表中的每个元素。从ListBuffer 中获取元素i 意味着逐步遍历列表的i 元素。

      索引ListBufferO(n),在最坏的情况下,冒泡排序是O(n^2),所以你的算法是O(n^3),如果n 很大,它会变得非常慢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多