Asi*_*sif 7 performance scala list apache-spark elementwise-operations
我可以使用Zipped函数进行像 sum 这样的元素操作。让我有两个列表L1和L2,如下所示
val L1 = List(1,2,3,4)
val L2 = List(5,6,7,8)
Run Code Online (Sandbox Code Playgroud)
我可以按以下方式计算元素总和
(L1,L2).zipped.map(_+_)
Run Code Online (Sandbox Code Playgroud)
结果是
List(6, 8, 10, 12)
Run Code Online (Sandbox Code Playgroud)
正如预期的那样。
我在我的实际代码中使用Zipped函数,但它需要太多时间。实际上,我的列表大小超过1000,我有超过1000 个列表,我的算法是迭代的,迭代次数可能高达10 亿。
在代码中,我必须做以下事情
list =( (L1,L2).zipped.map(_+_).map (_ * math.random) , L3).zipped.map(_+_)
Run Code Online (Sandbox Code Playgroud)
的尺寸L1,L2和L3是相同的。此外,我必须在集群上执行我的实际代码。
在 Scala 中对 List 进行元素求和的最快方法是什么?
一种选择是使用流实现,利用惰性可以提高性能。
使用LazyList 的 示例(在 Scala 中引入2.13)。
def usingLazyList(l1: LazyList[Double], l2: LazyList[Double], l3: LazyList[Double]): LazyList[Double] =
((l1 zip l2) zip l3).map {
case ((a, b), c) =>
((a + b) * math.random()) + c
}
Run Code Online (Sandbox Code Playgroud)
以及使用fs2.Stream 的示例(由库引入fs2)。
import fs2.Stream
import cats.effect.IO
def usingFs2Stream(s1: Stream[IO, Double], s2: Stream[IO, Double], s3: Stream[IO, Double]): Stream[IO, Double] =
s1.zipWith(s2) {
case (a, b) =>
(a + b) * math.random()
}.zipWith(s3) {
case (acc, c) =>
acc + c
}
Run Code Online (Sandbox Code Playgroud)
但是,如果这些仍然太慢,最好的选择是使用普通数组。
下面是一个使用ArraySeq (2.13也在 Scala 中引入)的示例,它至少会保留不变性。如果您愿意,可以使用原始数组,但要小心。
(如果您愿意,您也可以使用collections-parallel module来提高性能)
import scala.collection.immutable.ArraySeq
import scala.collection.parallel.CollectionConverters._
def usingArraySeq(a1: ArraySeq[Double], a2: ArraySeq[Double], a3: ArraySeq[Double]): ArraySeq[Double] = {
val length = a1.length
val arr = Array.ofDim[Double](length)
(0 until length).par.foreach { i =>
arr(i) = ((a1(i) + a2(i)) * math.random()) + a3(i)
}
ArraySeq.unsafeWrapArray(arr)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
298 次 |
| 最近记录: |