Scala Language
Parallella samlingar
Sök…
Anmärkningar
Parallella samlingar underlättar parallell programmering genom att dölja detaljer på låg nivå. Detta gör det enkelt att dra nytta av multikärnarkitekturer. Exempel på parallella samlingar inkluderar ParArray
, ParVector
, mutable.ParHashMap
, immutable.ParHashMap
och ParRange
. En fullständig lista finns i dokumentationen .
Skapa och använda parallella samlingar
För att skapa en parallellsamling från en sekvensiell samling, ring par
metoden. För att skapa en sekventiell samling från en parallellsamling, ring seq
metoden. Detta exempel visar hur du förvandlar en vanlig Vector
till en ParVector
och sedan tillbaka igen:
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
kan kedjas, så att du kan konvertera en sekventiell samling till en parallellsamling och omedelbart utföra en åtgärd på den:
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)
I dessa exempel delas arbetet faktiskt ut till flera behandlingsenheter och kopplas sedan samman igen efter det att arbetet är slutfört - utan att kräva utvecklarens ingripande.
Fallgropar gropar~~POS=HEADCOMP
Använd inte parallella samlingar när samlingselementen måste tas emot i en specifik ordning.
Parallella samlingar utför operationer samtidigt. Det betyder att allt arbete delas upp i delar och distribueras till olika processorer. Varje processor känner inte till det arbete som andra utför. Om ordningen på insamlingen är viktig är det arbete som bearbetas parallellt nondeterministiskt. (Att köra samma kod två gånger kan ge olika resultat.)
Icke-associerande verksamheter
Om en operation är icke-associerande (om exekveringsordningen är viktig), blir resultatet på en parallelliserad samling nondeterministisk.
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
Bieffekter
Åtgärder som har biverkningar, såsom foreach
, kanske inte utförs efter önskemål på parallella samlingar på grund av rasförhållanden. Undvik detta genom att använda funktioner som inte har några biverkningar, till exempel reduce
eller 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...