Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
scala:使用并行集合执行foreach,然后在每个分区上执行其他操作?_Scala - Fatal编程技术网

scala:使用并行集合执行foreach,然后在每个分区上执行其他操作?

scala:使用并行集合执行foreach,然后在每个分区上执行其他操作?,scala,Scala,我有一个Seq项目,我需要对每个项目做些什么,然后执行最后一个不需要任何输入的步骤。我想使用PAR来加速这一点:将 SEQ 分割成分区,并在每个分区中对每一个项目做一些事情,并为每个分区执行最后一步。我希望最后一步在处理特定分区的线程中运行。有办法吗aggregate()似乎做得不对 下面是一些示例代码: // non-parallel case val mySeq = Seq[Item] mySeq foreach { actOnItem(_) } doFinalStep() // idea

我有一个
Seq
项目,我需要对每个项目做些什么,然后执行最后一个不需要任何输入的步骤。我想使用PAR来加速这一点:将 SEQ 分割成分区,并在每个分区中对每一个项目做一些事情,并为每个分区执行最后一步。我希望最后一步在处理特定分区的线程中运行。有办法吗
aggregate()
似乎做得不对

下面是一些示例代码:

// non-parallel case
val mySeq = Seq[Item]
mySeq foreach { actOnItem(_) }
doFinalStep()

// ideal par case
val mySeq = Seq[Item]
mySeq.par foreachThenDoFinalStepAfterPartition { actOnItem(_), doFinalStep }

我假设
actOnItem
会产生
doFinalStep
所使用的某种副作用。由于同时存在多个副作用组,每个副作用组现在都需要使用
doFinalStep
进行处理,因此您必须在并发数据结构中跟踪不同组的不同副作用。如果不知道
actOnItem
doFinalStep
的具体功能,很难将其转换为更具功能性的样式。你可以这样做:

class SF { /* whatever your sideeffect is */ }

val ac = new java.util.concurrent.atomic.AtomicInteger(0)
val sfmap = new java.util.concurrent.ConcurrentHashMap[Int, SF]()
def newSideeffectIndex() = {
  val i = ac.fetchAndIncrement()
  sfmap.put(i, new SF())
  i
}

val mySeq = Seq[Item]()
mySeq.aggregate(-1)((u, x) => actOnItem(u, x), (u1, u2) => {
  doFinalStep(u1)
  doFinalStep(u2)
})

def actOnItem(u0: Int, x: Item) {
  val u = if (u0 == -1) newSideeffectIndex() else u0

  // do whatever you need to do with `x`
  // ...

  val sf = map.get(u)
  // do something with `sf` - update it somehow based on `x`

  u
}

def doFinalStep(u: Int) {
  val sf = map.get(u)

  if (sf != null) {
    // do the final step here using `sf`
  }

  map.remove(u)
}

说明:每个新分区都以聚合值-1开始。聚合部分(第一个闭包)将在检测到-1时初始化当前分区的聚合值。初始化将选取一个唯一的整数,并创建一个包含副作用的SF对象。之后,它将处理当前元素,然后更新副作用。在缩减步骤中,您知道已经处理了分区,因此您可以对该分区执行最后一步,并将其从并发映射中删除。

我假设
ActionItem
会产生
doFinalStep
使用的某种副作用。由于同时存在多个副作用组,每个副作用组现在都需要使用
doFinalStep
进行处理,因此您必须在并发数据结构中跟踪不同组的不同副作用。如果不知道
actOnItem
doFinalStep
的具体功能,很难将其转换为更具功能性的样式。你可以这样做:

class SF { /* whatever your sideeffect is */ }

val ac = new java.util.concurrent.atomic.AtomicInteger(0)
val sfmap = new java.util.concurrent.ConcurrentHashMap[Int, SF]()
def newSideeffectIndex() = {
  val i = ac.fetchAndIncrement()
  sfmap.put(i, new SF())
  i
}

val mySeq = Seq[Item]()
mySeq.aggregate(-1)((u, x) => actOnItem(u, x), (u1, u2) => {
  doFinalStep(u1)
  doFinalStep(u2)
})

def actOnItem(u0: Int, x: Item) {
  val u = if (u0 == -1) newSideeffectIndex() else u0

  // do whatever you need to do with `x`
  // ...

  val sf = map.get(u)
  // do something with `sf` - update it somehow based on `x`

  u
}

def doFinalStep(u: Int) {
  val sf = map.get(u)

  if (sf != null) {
    // do the final step here using `sf`
  }

  map.remove(u)
}

说明:每个新分区都以聚合值-1开始。聚合部分(第一个闭包)将在检测到-1时初始化当前分区的聚合值。初始化将选取一个唯一的整数,并创建一个包含副作用的SF对象。之后,它将处理当前元素,然后更新副作用。在缩减步骤中,您知道该分区已被处理,因此您可以对该分区执行最后一步,并将其从并发映射中删除。

您看到了吗?您能再描述一下吗?为什么在处理每批元素后都要做一些特殊的事情?@amir该链接与我的用例无关。@axel22处理每个元素会积累一些数据。最后我想用这些数据做点什么。我可以很容易地移动它,使其累积一个返回值,但我只想为每个分区处理一次累积。。。聚合所做的哪些部分不符合您的要求?您看到了吗?您能再描述一下吗?为什么在处理每批元素后都要做一些特殊的事情?@amir该链接与我的用例无关。@axel22处理每个元素会积累一些数据。最后我想用这些数据做点什么。我可以很容易地移动它,使其累积一个返回值,但我只想为每个分区处理一次累积。。。聚合所做的哪些部分不符合您的要求?