【问题标题】:How to merge and aggregate 2 Maps in scala most efficiently?如何最有效地在scala中合并和聚合2个地图?
【发布时间】:2018-08-31 17:50:26
【问题描述】:

我有以下 2 张地图:

val map12:Map[(String,String),Double]=Map(("Sam","0203") -> 16216.0, ("Jam","0157") -> 50756.0, ("Pam","0129") -> 3052.0)
val map22:Map[(String,String),Double]=Map(("Jam","0157") -> 16145.0, ("Pam","0129") -> 15258.0, ("Sam","0203") -> -1638.0, ("Dam","0088") -> -8440.0,("Ham","0104") -> 4130.0,("Hari","0268") -> -108.0, ("Om","0169") -> 5486.0, ("Shiv","0181") -> 275.0, ("Brahma","0148") -> 18739.0)

在第一种方法中我使用 foldLeft 来实现合并和累积:

val t1 = System.nanoTime()
val merged1 = (map12 foldLeft map22)((map22, map12) => map22 + (map12._1 -> (map12._2 + map22.getOrElse(map12._1, 0.0))))
val t2 = System.nanoTime()
println(" First Time taken :"+ (t2-t1))

在第二种方法中,我尝试使用支持并行操作的聚合()函数:

def merge(map12:Map[(String,String),Double], map22:Map[(String,String),Double]):Map[(String,String),Double]=
  map12 ++ map22.map{case(k, v) => k -> (v + (map12.getOrElse(k, 0.0)))}

val inArr= Array(map12,map22)

val t5 = System.nanoTime()
val mergedNew12 = inArr.par.aggregate(Map[(String,String),Double]())(merge,merge)
val t6 = System.nanoTime()
println(" Second Time taken :"+ (t6-t5))

但我注意到 foldLeft 比聚合快得多。

我正在寻求有关如何使此操作最有效的建议。

【问题讨论】:

  • 你的数组有2个元素,所以当你创建.par数组时,你认为Scala会为.aggregate创建多少块?我相信答案是 1。
  • 你是对的,这种编码方法不适合我的问题。在我的代码中,我有 2 个地图,我在其上使用 foldLeft 来聚合和合并地图。地图中将包含大量数据(数千行)。性能是一个问题。所以我试图找出更好的方法。
  • 是否需要拥有不可变的Maps?在我的机器上将一个可变的 Map 合并到另一个中比 foldLeft 快约 5 倍(取决于您需要复制多少键)。
  • 我在想,如果我将 foldLeft 转换为 fold 可能会获得并行性。

标签: scala parallel-processing parallel-collections


【解决方案1】:

如果您希望通过使用 par 运行更高效的聚合,请尝试使用 Vector 而不是 Array,它是并行算法的最佳集合之一。

另一方面,并​​行工作有一些开销,所以如果数据不足,则不方便。

根据你给我们的数据,Vector.par.aggregate 比 Array.par.aggregate 好,但 Vector.aggregate 比 foldLeft 好。

val inVector= Vector(map12,map22)

val t7 = System.nanoTime()
val mergedNew12_2 = inVector.aggregate(Map[(String,String),Double]())(merge,merge)
val t8 = System.nanoTime()
println(" Third Time taken :"+ (t8-t7))

这是我的时代

First Time taken :6431723
Second Time taken:147474028
Third Time taken :4855489

【讨论】:

  • 第一次拍摄:2085636 第二次拍摄:4611369 第三次拍摄:3220944。这些是我机器上的时间。我一直得到这样的结果,其中 foldLeft 在大多数测试运行中是最有效的。我可以复制你的结果模式,可能每 10 次运行一次。
  • 可能是你的集合太小,导致并行执行的开销大于收益?只是猜测。
猜你喜欢
  • 1970-01-01
  • 2010-11-18
  • 2023-03-31
  • 2014-10-13
  • 2016-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
相关资源
最近更新 更多