2012-08-07 135 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