14. 並列性、並行性、非同期性
14.1. 並列性
一般的な状況では、プログラム内でのタスクは、順次実行されます。
しようとしていることにかなりの時間がかかる場合、これが問題になることがあります。
簡単に言って、Perl6には物事を並列に実行する機能があります。
ここで、「並列性」には2種類の違った意味があることに注意しましょう:
-
タスク並列性: 2つ(あるいはそれ以上)の独立した式が並列に実行されること
-
データ並列性: 1つの式がリストの要素ひとつひとつに並列に適用されること
2番目の例から先に見てみましょう。
14.1.1. データ並列性
my @array = (0..50000); # 配列の作成
my @result = @array.map({ is-prime $_ }); # 配列の各要素に対して is-prime を呼ぶ
say now - INIT now; # スクリプトの実行にかかった時間を出力する
上でしている操作は一つだけです @array.map({ is-prime $_ })
is-prime
サブルーチンが配列の各要素に対して、順次呼ばれています:
まず is-prime @array[0]
次に is-prime @array[1]
次に is-prime @array[2]
と続きます。
is-prime
を配列の複数要素に対して同時に呼ぶことができます:my @array = (0..50000); # 配列の作成
my @result = @array.race.map({ is-prime $_ }); # 配列の各要素に対して is-prime を呼ぶ
say now - INIT now; # スクリプトの実行にかかった時間を出力する
式の中で race
が使われていることに注意してください。
このメソッドを使うことで、配列の各要素に対する並列実行をすることができます。
両方の例(race
ありとなし)を実行して、スクリプト終了までの時間を比べてみてください。
race
hyper
両方の例を実行すると、片方では数字の順に出力され、もう片方ではバラバラに出力されます。 |
14.1.2. タスク並列性
my @array1 = (0..49999);
my @array2 = (2..50001);
my @result1 = @array1.map( {is-prime($_ + 1)} );
my @result2 = @array2.map( {is-prime($_ - 1)} );
say @result1 == @result2;
say now - INIT now;
-
2つの配列を定義します
-
それぞれの配列に対して別の操作をして、その結果を保存します
-
それから、二つの配列が同じであることをチェックします
このスクリプトでは、 @array1.map( {is-prime($_ + 1)} )
が終わるのを待って、
それから @array2.map( {is-prime($_ - 1)} )
を評価しています。
それぞれの配列に対する操作は、お互いに影響しません。
my @array1 = (0..49999);
my @array2 = (2..50001);
my $promise1 = start @array1.map( {$_ + 1} );
my $promise2 = start @array2.map( {$_ - 1} );
my @result1 = await $promise1;
my @result2 = await $promise2;
say @result1 == @result2;
say now - INIT now;
start
メソッドはコードを評価して、 プロミス(約束)型のオブジェクト 略して プロミス(約束) を返します。
コードが問題なく評価されれば、その プロミス は 守られ ます。
コードが例外を投げれば、その プロミス は 破られ ます。
await
メソッドは プロミス を待ちます。
もしプロミスが 守られ れば、帰ってきた値を得ます。
もしプロミスが 破られ れば、投げられた例外を得ます。
それぞれのスクリプトの実行にかかった時間をチェックしてみてください。
並列化には、必ずスレッド化のオーバーヘッドがあります。もし計算速度の向上よりもオーバーヘッドの方が大きい場合には、そのスクリプトは遅くなるでしょう。 これが、 race 、 hyper 、 start と await を比較的単純なスクリプトで使うと、スクリプトが実際には遅くなってしまう理由です。
|
14.2. 並行性、非同期性
並行プログラミング、非同期プログラミングについて詳しくは、 http://doc.perl6.org/language/concurrency(英語)を参照してください。 |