Perl 6 簡單的並行

gaorongchao1990626發表於2016-01-06

Perl 6 簡單的並行

以下內容摘取於:Perl Introduction第14節
http://perl6intro.com/#_parallelism_concurrency_and_asynchrony

資料的平行計算

什麼是資料的並行呢?就是有一個大的資料列表,每一個資料都用相同的處理方式,普通的方式我們會一個一個的處理。
那麼並行就是可以分為部分,同時進行處理。
下面有一個很簡單的例子
判斷1到500000是不是質數

my @array = (0..500000);                     
my @result = @array.map({ is-prime $_ });
say now - INIT now;   

上面的程式碼執行時間為:95.1329786

如果用並行的方式執行呢?

my @array = (0..500000);                     
my @result = @array.race.map({ is-prime $_ });
say now - INIT now;   

然後只聽到電腦狂響,然後用時37.98698062,節省了接近一分鐘,效果還是有的。

這時有一個問題,因為資料的並行是把資料拆成幾個部分,分別計算,所有計算的順序不是按照資料的順序來的。
但是有時候我們希望我們得到的最後結果還是按照原始的資料順序,沒有問題,Perl 6 還提供了一種下面一種方式

my @array = (0..500000);                     
my @result = @array.hyper.map({ is-prime $_ });
say now - INIT now;   

時間比上面慢了一秒鐘。

可以試試下面的程式碼,看看輸出的順序。

#race
my @array = (1..1000);
my @result = @array.race.map( {$_ + 1} );
@result>>.say;
#hyper
my @array = (1..1000);
my @result = @array.hyper.map( {$_ + 1} );
@result>>.say;

多工的並行

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;

上面的程式主要乾了這麼一件事情:
1、有兩個不同的陣列,
2、對第一個陣列,先把每個元素加一,然後判斷是否是質數。
接著,對第二個陣列,先把每個元素減一,然後判斷是否是質數。
3、然後判斷兩個結果是否一樣

上面程式執行一共用了17秒。

上面分別判斷是否是質數的過程,是有先後順序的,如何讓兩個任務同時進行呢?也非常簡單。

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;

竟然只用了0.57秒,是出了什麼問題呢?不知道,差距也太大了吧。

上面程式首先用start方法啟動了程式碼(?),然後,返回了一個Promise的型別或者說是一個簡短的Promise(我也不知道是什麼意思)
如果程式碼執行正常,那麼Promise會被保留下去。
如果程式碼出錯了,那麼Promise會中斷。

然後await在苦苦等待上面的Promise,如果上面的Poomise執行的很順利,那麼await 會等正確的返回值。如果出錯了,那麼會得到異常值。

相關文章