我有一个算法,我可以创建两个这样的二维数组:
TYPE
TPtrMatrixLine = array of byte;
TCurMatrixLine = array of integer;
TPtrMatrix = array of TPtrMatrixLine;
TCurMatrix = array of TCurMatrixLine;
function x
var
PtrsMX: TPtrMatrix;
CurMx : TCurMatrix;
begin
{ Try to allocate RAM }
SetLength(PtrsMX, RowNr+1, ColNr+1);
SetLength(CurMx , RowNr+1, ColNr+1);
for all rows do
for all cols do
FillMatrixWithData; <------- CPU intensive task. It could take up to 10-20 min
end;
两个矩阵的维度始终相同。 通常矩阵中只有2000行和2000列,但有时它可以高达25000x6000,因此对于两个矩阵我需要146.5 + 586.2 = 732.8MB的RAM。 问题是这两个块需要连续,所以在大多数情况下,即使现代计算机上的500-600MB空闲RAM看起来不多,我的RAM也用完了。
该算法使用基于该单元的邻居的数据填充阵列的单元。这些操作只是增加和减少。
由于TCurMatrixLine使用整数来存储数据,因此它需要很多或RAM。不幸的是,存储的值可能有符号,所以我不能使用Word而不是整数。 SmallInt太小(我的值比SmallInt大,但比Word小)。我希望如果有任何其他方法来实现它,它不需要增加很多开销,因为处理具有如此多行/列的矩阵已经花费了大量时间。换句话说,我希望降低内存需求不会增加处理时间。
知道如何降低内存要求吗? [我使用Delphi 7]
更新 有人建议我的数组的每一行都应该是一个独立的单维数组。 我根据需要创建了很多行(数组)并将它们存储在TList中。听起来很不错。显然,分配这么小的内存块没有问题。但我担心它会对速度产生巨大影响。我现在用
TCurMatrixLine = array of integer;
TCurMatrix = array of TCurMatrixLine;
因为它比TCurMatrix= array of array of integer
快(因为数据放在内存中的方式)。因此,在独立行中断开数组可能会影响速度。
答案 0 :(得分:4)
使用带符号的2字节整数的建议将极大地帮助您。
另一个有用的策略是通过将LARGE_ADDRESS_AWARE
添加到.dpr文件来将您的exe标记为{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
。这只有在64位Windows上运行时才有用,并且会将地址空间从2GB增加到4GB。
它可能无法在Delphi 7上运行(我好像记得您使用的是D7)并且您必须使用FastMM,因为旧的Borland内存管理器与大地址空间不兼容。如果$SetPEFlags
不可用,您仍然可以使用EDITBIN
标记exe。
如果您仍然遇到困难,那么另一个技巧是分配较小的内存子块并使用包装类来处理映射索引到适当的子块并在其中进行偏移。您可以使用默认索引属性使其对调用代码透明。
当然,像这样的块分配方法确实会产生一些处理开销,但如果你遇到连续块的问题,这是你最好的选择。
答案 1 :(得分:2)
如果CurMx的元素的绝对值适合单词,则可以将其存储在单词中,并使用另一个布尔数组作为其符号。它减少了每个元素的1个字节。
答案 2 :(得分:1)
您是否考虑过在堆上手动分配数据结构? ...并测量这将如何影响内存使用和性能?
使用堆实际上可能会提高速度并减少内存使用量,因为您可以避免将整个数组从一个内存段复制到另一个内存段。 (例如,如果使用非const开放数组参数声明FillMatrixWithData
)。