我有一个大小像2 GB的数组(填充音频样本)。现在我想为该数组应用过滤器。该滤波器产生的样本比输入源多50%。所以现在我需要创建一个大小为3 GB的新阵列。现在我给了5 GB的内存。但是,如果此过滤器只能在该源阵列上运行,并且在此阵列中只需要更多空间。 问题:我可以在C#中分配一个可以调整大小的内存,而无需创建第二个内存块,然后删除第一个内存块吗? 我只是想,如果PC中的内存分为4 kB页面(或更多),那么为什么C#不能(?)使用那个好的功能?
答案 0 :(得分:3)
问题:我可以在C#中分配一个可以调整大小的内存,而无需创建第二个内存块,然后删除第一个内存块吗?
不,您无法在.NET中调整数组大小。如果要增加数组的大小,则必须创建一个新的更大的数组,并将现有数组中的所有数据复制到新数组中。
为了解决这个问题,你可以提供自己的“数组”实现,基于分配较小的内存块,但将其作为一个大的数据缓冲区。一个例子是StringBuilder
,它基于一个字符块的实现,每个块都是一个单独的Char[]
数组。
另一种选择是使用P / Invoke来访问低级内存管理功能,如VirtualAlloc,允许您提前预留内存页面。您需要在64位进程中执行此操作,因为32位进程的虚拟地址空间仅为4 GB。您可能还需要使用unsafe code and pointers。
答案 1 :(得分: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;
}
为每次访问数组添加索引检查和减法开销。对于某些情况,这也可以变得更聪明。例如,对于您不需要访问扩展的部分,您可以使用更快的循环,对于需要写入扩展部分的部分,您可以使用较慢的版本(两个连续的循环)。