使用并行数组处理此数据的首选方法

时间:2011-05-11 07:34:31

标签: scala parallel-arrays

想象一系列java.io.File个对象。序列没有任何特定的顺序,它在目录遍历后填充。文件的名称可以是这样的:

/some/file.bin
/some/other_file_x1.bin
/some/other_file_x2.bin
/some/other_file_x3.bin
/some/other_file_x4.bin
/some/other_file_x5.bin
...
/some/x_file_part1.bin
/some/x_file_part2.bin
/some/x_file_part3.bin
/some/x_file_part4.bin
/some/x_file_part5.bin
...
/some/x_file_part10.bin

基本上,我可以有3种类型的文件。第一种类型是简单类型,只有.bin扩展名。第二种类型的文件是从_x1.bin_x5.bin形成的文件。第三种类型的文件可以由10个较小的部分组成,从_part1_part10。 我知道命名可能很奇怪,但这是我必须要处理的事情:)

我想将文件组合在一起(文件的所有部分应该一起处理),我正在考虑使用并行数组来完成这项工作。我不确定的是如何执行reduce / acumulation部分,因为所有线程都将在同一个数组上工作。

val allBinFiles = allBins.toArray // array of java.io.File

我正在考虑处理类似的事情:

val mapAcumulator = java.util.Collections.synchronizedMap[String,ListBuffer[File]](new java.util.HashMap[String,ListBuffer[File]]())

allBinFiles.par.foreach { file =>
   file match {
      // for something like /some/x_file_x4.bin nameTillPart will be /some/x_file
      case ComposedOf5Name(nameTillPart) => {
          mapAcumulator.getOrElseUpdate(nameTillPart,new ListBuffer[File]()) += file
      }
      case ComposedOf10Name(nameTillPart) => {
          mapAcumulator.getOrElseUpdate(nameTillPart,new ListBuffer[File]()) += file
      }
      // simple file, without any pieces
      case _ => {
          mapAcumulator.getOrElseUpdate(file.toString,new ListBuffer[File]()) += file
      }
   }
}

我正在考虑像上面代码中所示的那样做。拥有文件的提取器,并使用路径的一部分作为映射中的键。例如,/some/x_file可以将值/some/x_file_x1.bin保存为/some/x_file_x5.bin。我也认为可以有更好的方法来处理这个问题。我会对你的意见感兴趣。

1 个答案:

答案 0 :(得分:1)

另一种方法是使用groupBy

val mp = allBinFiles.par.groupBy {
  case ComposedOf5Name(x) => x
  case ComposedOf10Name(x) => x
  case f => f.toString
}

这将返回并行的文件数组(ParMap[String, ParArray[File]])的并行映射。如果您想要从这一点开始连续的文件序列映射:

val sqmp = mp.map(_.seq).seq

为了确保并行性能够发挥作用,请确保并行数组中有足够的元素(10k +)。