2017-07-14 58 views
5

教堂的減少量目前忽略了變量的初始值。這意味着此代碼嵌套減少 - 在Chapel中寫這些的最習慣的方法是什麼?

var x: int; 
for i in 1..3 { 
    forall j in 1..10 with (+ reduce x) { 
    x += 1; 
    } 
} 

writeln(x); 

返回10而不是30,因爲此用戶天真地以爲。雖然這種行爲沒有問題(關於還原子句的記錄中記載了這一點 - 我只是沒有認真思考),事實證明,如果我想獲得30(通過在兩個循環中累積),我需要實際上是手工完成的。我認爲這將是很優雅和對稱的for循環也有一個reduce意圖....即我想寫

var x: int; 
for i in 1..3 with (+ reduce x) { 
    forall j in 1..10 with (+ reduce x) { 
    x += 1; 
    } 
} 

writeln(x); 

注意,即使在合計數值的情況下,我需要介紹一個臨時變量。對於最大/最小的操作,需要更加小心。

是否有理由不支持reduce for循環內的意圖?或者,有沒有一種更習慣(Chapel-rrific)的方式來做到這一點?

更新:我對此的看法越多,我的建議代碼在外部for被替換爲forall的情況下也不會很明顯。我認爲問題是變量是任務本地的,而不是迭代本地的,所以減少只會發生在任務上。所以人們仍然需要一個單獨的內部減少步驟。這將刪除是需要一個臨時變量。

我覺得更多的首要問題是什麼做的這些各種各樣嵌套削減的正確的方法是...

+1

在你的問題的第一個程序現在可以如你預期Chapel的主分支(https://github.com/chapel-lang/chapel/pull/7351),這個改變應該在2017年10月發佈的Chapel 1.16中提供。 – Brad

+0

順便說一句,當我用'forall'和一個類似的縮減意圖替換外部'for'時,你的代碼也工作(生成'30')。 – Brad

+0

原始代碼塊現在可以按照您在Chapel 1.16版本中的預期工作。感謝您提出這個建議。 – Brad

回答

5

在我看來,這是在教堂的減少意圖設計的監督。具體來說,雖然我認爲每個任務忽略原始變量在將其還原變量的個人副本初始化爲身份時的價值(如您目前已完成的),但我認爲這些任務的貢獻應該合併回到原始變量在並行循環結束時的值,而不是簡單地在原始值相互組合時覆蓋原始值。這將使您的原始嘗試的工作,你的預期,也將遵循什麼樣的OpenMP不一致,如建議通過下面的C例子得到35作爲它的結果:

#include <stdio.h> 
#include <omp.h> 

int main(int argc, char* argv[]) { 
    int tot = 5; 
    for (int i=0; i<3; i++) { 
    #pragma omp parallel for reduction(+:tot) 
    for (int j=0; j<10; j++) { 
     tot += 1; 
    } 
    } 
    printf("tot is: %d\n", tot); 
} 

我建議提交一個bug /功能請求在Chapel GitHub issues page上提倡這種行爲。

由於教堂1.15.0的,要解決這一辦法是在連續的循環中人工完成的減小,如下:

config var tot: int = 5; 

for i in 1..3 { 
    var subtot: int; 
    forall j in 1..10 with (+ reduce subtot) do 
    subtot += 1; 
    tot += subtot; 
} 

writeln("tot is: ", tot); 
相關問題