调整大数组的大小

时间:2012-08-07 08:53:53

标签: c# arrays

我有一个大小像2 GB的数组(填充音频样本)。现在我想为该数组应用过滤器。该滤波器产生的样本比输入源多50%。所以现在我需要创建一个大小为3 GB的新阵列。现在我给了5 GB的内存。但是,如果此过滤器只能在该源阵列上运行,并且在此阵列中只需要更多空间。 问题:我可以在C#中分配一个可以调整大小的内存,而无需创建第二个内存块,然后删除第一个内存块吗? 我只是想,如果PC中的内存分为4 kB页面(或更多),那么为什么C#不能(?)使用那个好的功能?

2 个答案:

答案 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;
}

为每次访问数组添加索引检查和减法开销。对于某些情况,这也可以变得更聪明。例如,对于您不需要访问扩展的部分,您可以使用更快的循环,对于需要写入扩展部分的部分,您可以使用较慢的版本(两个连续的循环)。