2012-08-07 136 views
2

我有一個數組,其大小像2 GB(填充音頻樣本)。現在我想爲該數組應用一個過濾器。這個濾波器產生的樣本比輸入源多50%。所以現在我需要創建大小爲3 GB的新數組。現在我給了5 GB的內存使用。但是,如果此過濾器只能在該源陣列上運行,並且只需要該陣列中更多的空間。 問題:我可以在C#中分配一個可以調整大小的內存嗎?不創建第二個內存塊,然後刪除第一個? 我只是想,如果PC中的內存被分成4 kB頁面(或更多),那爲什麼C#不能(?)使用那個好功能?調整大陣列大小

+2

不相關,但這是很多要存儲在內存中 - 您可能會遇到其他問題,如'2GB限制' - 請參閱這裏的問題和答案:http://stackoverflow.com/questions/1087982 /單個對象仍然限制到2 gb-in-size-in-clr-4-0 – Paddy 2012-08-07 08:57:12

+0

「所以現在我需要創建一個大小爲3 GB的新數組,現在我給出了5 GB的內存「。爲什麼不直接傳輸數據? – NPSF3000 2012-08-07 09:11:47

+0

由於數據流速度非常慢: – zgnilec 2012-08-07 09:13:59

回答

3

如果您的過濾器可以就地工作,只是在開始時分配50%的空間。所有你需要知道的是原始樣本的實際長度。

如果這些代碼並不總是工作,你不想提前消耗更多的內存,你可以分配一半的原始數組(擴展陣列),並檢查您的訪問涉及部分:

byte[] myOriginalArray = new byte[2GB]; // previously allocated 

byte[] myExtensionArray = new byte[1GB]; // 50% of the original 
for(... my processing code of the array ...) 
{ 
    byte value = read(index); 
    ... process the index and the value here 
    store(index, value); 
} 

byte read(int index) 
{ 
    if(index < 2GB) return myOriginalArray[index]; 
    return myExtensionArray[index - 2GB]; 
} 

void store(int index, byte value) 
{ 
    if(index < 2GB) myOriginalArray[index] = value; 
    myExtensionArray[index - 2GB] = value; 
} 

您可以爲陣列的每次訪問添加索引檢查和減法開銷。在某些情況下,這也可以變得更聰明。例如,對於不需要訪問擴展的部分,可以使用較快的循環,對於需要寫入擴展部分的部分,可以使用較慢的版本(兩個連續循環)。

+0

Thx,但它不能在開始時分配更多內容,因爲結果樣本取決於用戶操作。 – zgnilec 2012-08-07 09:12:31

3

問題:我可以在C#中分配一個可以調整大小的內存嗎?不創建第二個內存塊,然後刪除第一個?

不,您不能在.NET中調整數組大小。如果你想增加一個數組的大小,你將不得不創建一個新的,更大的數組,並將現有數組中的所有數據複製到新數組中。

爲了解決這個問題,你可以提供你自己的「數組」實現,它基於分配更小的內存塊,但將其呈現爲一個大的數據緩衝區。一個例子是StringBuilder,它基於字符塊的實現,每個塊都是獨立的Char[]數組。

另一種選擇是使用P/Invoke來訪問低級別的內存管理功能,如VirtualAlloc,它允許您預先保留內存頁面。您需要在64位進程中執行此操作,因爲32位進程的虛擬地址空間僅爲4 GB。您可能還需要使用unsafe code and pointers

+0

這是否可以使用.DLL中的外部代碼執行? – zgnilec 2012-08-07 09:11:15