调整大数组的大小

本文关键字:数组 调整 | 更新日期: 2024-10-23 22:06:11

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

调整大数组的大小

如果您的过滤器可以在适当的位置工作,只需在开始时多分配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;
}

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

问题:我可以在C#中分配一个可以调整大小的内存吗?不需要创建第二个内存块,然后删除第一个内存块?

不可以,不能在.NET中调整数组的大小。如果要增加数组的大小,必须创建一个新的更大的数组,并将现有数组中的所有数据复制到新数组中。

为了解决这个问题,您可以提供自己的"数组"实现,该实现基于分配较小的内存块,但将其表示为一个大的数据缓冲区。这方面的一个例子是StringBuilder,它基于字符块的实现,每个块都是一个单独的Char[]数组。

另一种选择是使用p/Invoke来访问低级别内存管理功能,如VirtualAlloc,它允许您提前保留内存页。您需要在64位进程中执行此操作,因为32位进程的虚拟地址空间只有4GB。您可能还需要使用不安全的代码和指针。