在scala中减去两个数组的最快方法是什么?

Mik*_*der 6 scala micro-optimization scala-2.9

我有两个数组(我已经退出矩阵(Array [Array [Int]]),我需要从另一个中减去一个.

目前我正在使用这种方法,当我对它进行分析时,它就是瓶颈.

def subRows(a: Array[Int], b: Array[Int], sizeHint: Int): Array[Int] = {
   val l: Array[Int] = new Array(sizeHint)
   var i = 0
   while (i < sizeHint) {
     l(i) = a(i) - b(i)
     i += 1
   }
   l
 }
Run Code Online (Sandbox Code Playgroud)

我需要做数十亿次,所以速度的提高是有利的.

我已经尝试使用a List而不是a Array来收集差异并且速度更快但是当我将其转换回来时我失去了所有好处Array.

我确实修改了下游代码,List看看是否会有所帮助,但我需要不按顺序访问列表中的内容,所以再次失去任何收益.

似乎任何一种类型的转换都是昂贵的,我想知道是否有某种方法可以使用可能更快的地图等.

有没有更好的办法?


编辑

不知道我第一次做了什么!?

所以我用来测试它的代码是这样的:

def subRowsArray(a: Array[Int], b: Array[Int], sizeHint: Int): Array[Int] = {
  val l: Array[Int] = new Array(sizeHint)
  var i = 0
  while (i < sizeHint) {
    l(i) = a(i) - b(i)
    i += 1
  }
  l
}

def subRowsList(a: Array[Int], b: Array[Int], sizeHint: Int): List[Int] = {
  var l: List[Int] = Nil
  var i = 0
  while (i < sizeHint) {
    l = a(i) - b(i) :: l
    i += 1
  }
  l
}

val a = Array.fill(100, 100)(scala.util.Random.nextInt(2))
val loops = 30000 * 10000

def runArray = for (i <- 1 to loops) subRowsArray(a(scala.util.Random.nextInt(100)), a(scala.util.Random.nextInt(100)), 100)

def runList = for (i <- 1 to loops) subRowsList(a(scala.util.Random.nextInt(100)), a(scala.util.Random.nextInt(100)), 100)

def optTimer(f: => Unit) = {
  val s = System.currentTimeMillis
  f
  System.currentTimeMillis - s
}
Run Code Online (Sandbox Code Playgroud)

我认为我第一次这样做的结果恰恰相反......我必须误解或混淆方法.

我很抱歉提出一个糟糕的问题.

Rex*_*err 6

该代码是使用标准JVM管理单线程的最快代码.如果你认为List速度更快,你要么自欺欺人,要么不实际告诉我们你在做什么.把一个IntList需要两个对象创建:一个用于创建列表元素,和一个框的整数.对象创建所需的时间比数组访问长约10倍.所以以任何其他方式做到这一点真的不是一个成功的主张.

如果你真的,真的需要更快,并且必须保持单个线程,你应该切换到C++等,并明确使用SSE指令.例如,请参阅此问题.

如果你真的,真的需要更快,并且可以使用多个线程,那么最简单的是打包这样的一大块工作(即需要减去的合理数量的矢量对 - 可能至少有几百万每个块的元素)只要你的机器上的处理器数量,然后调用一个列表list.par.map(yourSubtractionRoutineThatActsOnTheChunkOfWork).

最后,如果你可以是破坏性的,

a(i) -= b(i)
Run Code Online (Sandbox Code Playgroud)

当然,内环更快.同样,如果你可以重复使用空间(例如with System.arraycopy),那么你最好不要继续分配空间.但是这会改变你所展示的界面.