Scala Language
並列コレクション
サーチ…
備考
並列コレクションは、低レベルの並列化の詳細を隠すことによって並列プログラミングを容易にします。これにより、マルチコア・アーキテクチャを容易に利用できます。並列コレクションの例には、 ParArray
、 ParVector
、 mutable.ParHashMap
、 immutable.ParHashMap
、 ParRange
などがありParRange
。完全なリストは、ドキュメントにあります 。
並列コレクションの作成と使用
順次コレクションから並列コレクションを作成するには、 par
メソッドを呼び出します。並列コレクションから順次コレクションを作成するには、 seq
メソッドを呼び出します。次の例では、通常のVector
をParVector
、再びParVector
Vector
に戻します。
scala> val vect = (1 to 5).toVector
vect: Vector[Int] = Vector(1, 2, 3, 4, 5)
scala> val parVect = vect.par
parVect: scala.collection.parallel.immutable.ParVector[Int] = ParVector(1, 2, 3, 4, 5)
scala> parVect.seq
res0: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5)
par
メソッドを連鎖させることができます。これにより、順次コレクションを並列コレクションに変換し、直ちにアクションを実行することができます。
scala> vect.map(_ * 2)
res1: scala.collection.immutable.Vector[Int] = Vector(2, 4, 6, 8, 10)
scala> vect.par.map(_ * 2)
res2: scala.collection.parallel.immutable.ParVector[Int] = ParVector(2, 4, 6, 8, 10)
これらの例では、実際には複数の処理単位に分けられ、その後、開発者の介入を必要とせずに作業が完了した後に再結合されます。
落とし穴
コレクション要素を特定の順序で受信する必要がある場合は、並列コレクションを使用しないでください。
並列コレクションは同時に操作を実行します。つまり、すべての作業が複数の部分に分割され、異なるプロセッサに分散されます。各プロセッサは、他の人が行っている作業を知らない。 コレクションの順序が重要な場合、並行して処理される作業は非決定的です。同じコードを2回実行すると異なる結果が得られます。
非連想操作
操作が非関連(実行順序が重要な場合)の場合、並列化されたコレクションの結果は非決定的になります。
scala> val list = (1 to 1000).toList
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10...
scala> list.reduce(_ - _)
res0: Int = -500498
scala> list.reduce(_ - _)
res1: Int = -500498
scala> list.reduce(_ - _)
res2: Int = -500498
scala> val listPar = list.par
listPar: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10...
scala> listPar.reduce(_ - _)
res3: Int = -408314
scala> listPar.reduce(_ - _)
res4: Int = -422884
scala> listPar.reduce(_ - _)
res5: Int = -301748
副作用
foreach
などの副作用を伴う操作は、競合状態のために並列化されたコレクションでは望ましく実行されないことがあります。これを回避するには、 reduce
やmap
などの副作用のない関数を使用しmap
。
scala> val wittyOneLiner = Array("Artificial", "Intelligence", "is", "no", "match", "for", "natural", "stupidity")
scala> wittyOneLiner.foreach(word => print(word + " "))
Artificial Intelligence is no match for natural stupidity
scala> wittyOneLiner.par.foreach(word => print(word + " "))
match natural is for Artificial no stupidity Intelligence
scala> print(wittyOneLiner.par.reduce{_ + " " + _})
Artificial Intelligence is no match for natural stupidity
scala> val list = (1 to 100).toList
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15...