Scala Language
Parallelle collecties
Zoeken…
Opmerkingen
Parallelle collecties maken parallelle programmering mogelijk door details van lage niveaus te verbergen. Dit maakt het gemakkelijk om te profiteren van multi-core architecturen. Voorbeelden van parallelle verzamelingen omvatten ParArray
, ParVector
, mutable.ParHashMap
, immutable.ParHashMap
en ParRange
. Een volledige lijst is te vinden in de documentatie .
Parallelle collecties maken en gebruiken
Roep de par
methode aan om een parallelle verzameling te maken van een opeenvolgende verzameling. seq
methode seq
aan om een opeenvolgende verzameling van een parallelle verzameling te maken. Dit voorbeeld laat zien hoe u van een gewone Vector
een ParVector
maakt en vervolgens weer terug:
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)
De par
methode kan worden gekoppeld, zodat u een opeenvolgende verzameling kunt omzetten in een parallelle verzameling en er onmiddellijk een actie op kunt uitvoeren:
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)
In deze voorbeelden wordt het werk in feite verdeeld over meerdere verwerkingseenheden en vervolgens weer samengevoegd nadat het werk is voltooid - zonder tussenkomst van de ontwikkelaar.
valkuilen
Gebruik geen parallelle collecties wanneer de collectie-elementen in een specifieke volgorde moeten worden ontvangen.
Parallelle collecties voeren tegelijkertijd bewerkingen uit. Dat betekent dat al het werk in delen is verdeeld en onder verschillende processors is verdeeld. Elke processor is zich niet bewust van het werk dat door anderen wordt gedaan. Als de volgorde van de verzameling van belang is, dan is parallel verwerkt niet-deterministisch. (Het tweemaal uitvoeren van dezelfde code kan verschillende resultaten opleveren.)
Niet-associatieve activiteiten
Als een bewerking niet-associatief is (als de volgorde van uitvoering ertoe doet), is het resultaat van een parallelle verzameling niet-deterministisch.
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
Bijwerkingen
Bewerkingen die bijwerkingen hebben, zoals foreach
, worden mogelijk niet uitgevoerd zoals gewenst op parallelle collecties vanwege race-omstandigheden. Vermijd dit door functies te gebruiken die geen bijwerkingen hebben, zoals reduce
of 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...