2010-09-18 8 views
10

Jakie są analogi QtConcurrent dla Scala (lub Java)? Tj. Uproszczona implementacja MapReduce, mapy równoległej i foldl. DziękujęScala analogi QtConcurrent

+0

patrz także http://stackoverflow.com/questions/1751953/concurrent-map-foreach-in-scala/1753224#1753224 – oluies

Odpowiedz

3

Możesz przejść długą drogę po prostu używając scala.actors.Futures i normalnego map/flatMap nad kolekcjami. Nie można jednak łatwo zrównoleglić fold.

Jeśli używasz wielu hostów, użyłbym Akka's do wysyłania i odbierania.

12

Możesz użyć Scala Parallel Collections. Obecnie są częścią nocnych wydawnictw Scala i zostaną wydane w Scala 2.9. Chodzi o to, że większość operacji dostępnych w zwykłych kolekcjach jest zrównoleglona, ​​dzięki czemu równoległe kolekcje mogą być używane w ten sam sposób.

Obecnie dostępnych jest kilka typów kolekcji - zakresy równoległe, równoległe i równoległe. Na przykład, można powołać się na równoległe map i fold operacji na równoległym tablicy tak:

scala> val pa = (0 until 10000).toArray.par 
pa: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, 1, 2, 3, 4, 5, 6,... 

scala> pa.map(_ + 1) 
res0: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 2, 3, 4, 5, 6, 7,... 

scala> pa map { v => if (v % 2 == 0) v else -v } 
res1: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, -1, 2, -3, 4, -5,... 

scala> pa.fold(0) { _ + _ } 
res2: Int = 49995000 

Istnieją inne czynności windykacyjne równolegle również dostępne. Zauważ, że fold musi przyjmować operatora asocjacyjnego - w powyższym przykładzie dodawanie jest asocjacyjne ((A + B) + C == A + (B + C)), tzn. Możesz dodawać podciągi liczb w dowolnej kolejności i zawsze będziesz uzyskać tę samą kwotę (reduce ma podobną umowę).

Jeszcze jedną rzeczą, o której należy pamiętać, jest to, że zamknięcia przenoszone do równoległych kolekcji są wywoływane jednocześnie. Jeśli mają one efekty uboczne, takie jak modyfikowanie zmiennej lokalnej w środowisku, dostępy te muszą być zsynchronizowane. Na przykład, można zrobić coś takiego:

scala> var a = 0                                         
a: Int = 0                                          

scala> pa foreach { a += _ }                                      

scala> a                                           
res1: Int = 49995000    

scala> a = 0 
a: Int = 0 

scala> pa foreach { a += _ } 

scala> a 
res7: Int = 49990086 

i mają różne wyniki za każdym razem, ponieważ foreach wywołuje { a += _ } równolegle. W powyższym przykładzie należy dokonać synchronizacji a, chronić za pomocą zamka lub atomu.

Ale pomysł polega na wykorzystaniu wbudowanych kombinatorów do wykonania zadania i skłania się ku programowaniu funkcjonalnemu, unikając lokalnych skutków ubocznych, jak w powyższym przykładzie.

Możesz chcieć przeczytać trochę więcej na temat swoich wewnętrznych mechanizmów w linkach podanych w drugiej odpowiedzi.

+0

Bardzo ładna odpowiedź z "nudge" z dala od mutacji ;-) –