2017-06-06 71 views
5

與其他語言不同,Chapel中沒有allocatenew語法用於在堆上分配數組,而是使用通常的「聲明」類語法。例如,在下面的代碼,I「聲明」兩個陣列在功能AB基於正式(虛設)參數:在Chapel中分配數組

proc test(n, D) 
{ 
    var A: [1..n] real; // local array 
    var B: [D] real;  // local array 

    writeln("A.domain = ", A.domain); 
    writeln("B.domain = ", B.domain); 
} 

test(3, {2..5});    // request small arrays 
test(10**7, {-10**7..10**7}); // request large arrays 

這給出以下結果:

A.domain = {1..3} 
B.domain = {2..5} 
A.domain = {1..10000000} 
B.domain = {-10000000..10000000} 

因爲沒有發生堆棧溢出(儘管B的大小很大),假設上面的語法總是在堆上分配AB而不管大小如何都可以嗎?

另外,域變量的賦值(或重新賦值)似乎扮演着數組分配(或重新賦值)的角色。例如,下面的代碼按預期工作。在這種情況下,分配是否始終發生在堆上(再次)?

var domC: domain(1); 
var C: [domC] real; 
writeln("C = ", C); 

domC = { 1..3 };  // assign a domain 
C = 7.0;    // assign some value to the array 
writeln("C = ", C); 

domC = { -1..5 };  // re-assign a domain 
writeln("C = ", C); 

結果:

C = 
C = 7.0 7.0 7.0 
C = 0.0 0.0 7.0 7.0 7.0 0.0 0.0 

最後,是它不需要用戶deallocatedelete手動這些陣列,但根據需要而系統會自動解除分配它們?

回答

3

可以假設上面的語法總是在堆上分配A和B,而不管它們的大小如何?

禮拜堂1.15.0的禮拜堂數組元素始終分配在堆上。我們已經討論過添加機制(例如,自定義域映射)或可能的優化,可能用於在適當的時候將數組的元素存儲在堆棧上,但尚未追求這些功能。請注意,雖然數組的元素分配在堆上,但數組也可以使用「就地」分配的運行時描述符來實現(例如,在您的示例中的堆棧上) - 此描述符指的是堆分配的元素。

另外,域變量的賦值(或重新賦值)似乎扮演着數組分配(或重新賦值)的角色。

這是正確的,這是值得強調的是,這是重新分配邏輯而不是物理導向概念。特別是,當數組的域被重新分配時,如果i同時位於舊域和新域的索引集中,則A[i]將繼續存儲相同的值。這就是爲什麼當你在上面的代碼中將domC{1..3}更改爲{-1..5}時,A[1..3]被保留下來,因爲它代表了這兩個集合的交集。

該分配是否總是出現在堆上(再次)?

是的,與初始數組分配一樣。

用戶無需手動釋放或刪除這些數組,而是系統根據需要自動釋放它們?

這是正確的,數組內存管理通常由實現來處理。一種手動管理數組內存的方法是使用一個數組字段(因爲類是手動內存管理的)。

+1

非常感謝您的解釋。我認爲有趣的是,賦值域變量意味着對數組(或與該域相關聯的所有數組)進行「調整大小」,並且自動完成必要的分配/重新分配。謝謝:) – roygvib

+0

[順便說一下,第一段中的下列句子「請注意,雖然數組的元素分配在_stack_上」可能是「請注意,儘管數組的元素分配在_heap_上」 ? (儘管它可能取決於解釋的上下文)] – roygvib

+0

感謝您指出我修復的拼寫錯誤。一旦域使用某種語言,它們似乎是調整數組大小的最自然/最明顯的方式,即使有一些學習曲線可以適應它。 – Brad