einen Code gegeben, die ein bisschen Mathe tut/für jede Zahl von 1 bis 500.000 Gießen, haben wir Optionen:Gibt es in Perl 6 eine schnelle parallele "for" -Schleife?
einfache for-Schleife:
for ^500000 -> $i { my $result = ($i ** 2).Str; }
. In meinem unwissenschaftlichen Benchmark dauert das 2,8 Sekunden.Die kanonischste parallele Version erledigt jedes Stück Arbeit in einem
Promise
, dann wartet auf das Ergebnis.await do for ^500000 -> $i { start { my $result = ($i ** 2).Str; } }
dauert 19 Sekunden. Das ist langsam! Das Erstellen eines neuen Versprechens muss zu viel Aufwand erfordern, um sich für solch eine einfache Berechnung zu lohnen.Mit einem parallelen
map
Operation ist ziemlich schnell. Mit 2,0 Sekunden scheint der Vorgang kaum langsam genug, um die Vorteile der Parallelisierung zu nehmen:(^500000).race.map: -> $i { my $result = ($i ** 2).Str; }
Die dritte Option scheint am besten. Leider liest es sich wie ein Hack. Wir sollten nicht map
Code für die Iteration im Sink-Kontext schreiben, weil andere, die "map" in der Quelle lesen, annehmen, dass der Zweck darin besteht, eine Liste zu erstellen, was nicht unsere Absicht ist. Es ist schlechte Kommunikation, map
auf diese Weise zu verwenden.
Gibt es einen kanonischen schnellen Weg, um die Parallelität von Perl 6 zu nutzen? Ein hyper Operator perfekt sein würde, wenn er einen Block statt nur Funktionen übernehmen könnte:
(^500000)».(-> $i { my $result = ($i ** 2).Str; }) # No such method 'CALL-ME' for invocant of type 'Int'
Sollte die Schleife nicht in der Zeit Null laufen, da sie keine Auswirkungen hat? – BarneySchmale
@BarneySchmale Sie haben gerade erklärt, warum ich 'map' anstelle von' for' nicht mag. In Perl 6 ist 'map' nicht faul, also funktioniert es wie' for'. (Genauer gesagt funktioniert es wie 'do for'.)' Map' wird für alle Listenelemente ausgeführt, auch wenn das Ergebnis nicht verwendet wird. Wenn Sie jedoch 'map' anstelle von' for' wählen, wird Ihnen mitgeteilt, dass das Ziel darin besteht, eine Liste zu erstellen, und in diesem Fall ist es nicht wahr. – piojo
@piojo 'map' ist fast immer faul. Versuchen Sie 'say [1..Inf] .map (* + 100) [1..10]'. Aiui ...Standardmäßig ist "for" A) wie eine "Map", die eifrig und nicht faul ist, und B) eine Kontrollflussanweisung anstelle eines Ausdrucks. Ein "do" wandelt eine Anweisung in einen Ausdruck um, indem der nachfolgende Code ausgeführt und die vom Code generierte Liste der Werte zurückgegeben wird. (Ohne es gibt ein 'for' überhaupt keine Werte zurück.) – raiph