只是好奇:我正在寻找一个理论问题的解决方案,以优化数据结构在应用程序中的使用。
假设有以下类型(如果有问题,当前使用DXE7):
type
TMyType1 = 0..4294967295;
TMyType2 = 0..65535;
TMyArrayType1 = array of TMyType1;
TMyArrayType2 = array of TMyType2;
我们现在需要做的是将TMyArrayType2
类型的数组“转换”为TMyArrayType1
。为什么?可能是为了向后或向前兼容的原因,也可能是为了尽可能地减少数据大小,但是在我们应用程序的大多数方法中只处理一种类型(这里是:TMyType1
),以避免重载许多方法来处理这两种类型,等等。比方说,两种数组类型都有各自的优点,因此不能用另一种类型替换。
由于TMyType2
的所有可能值都拟合到TMyType1
中,我们可以做如下操作:
procedure Convert(const[ref] ASource: TMyArrayType2; var ADest: TMyArrayType1);
var
ALen, i: Integer;
begin
ALen:= Length(ASource);
SetLength(ADest, ALen);
FOR i:=0 TO ALen-1 DO
begin
ADest[i]:= ASource[i];
end;
end;
编译,但是我们可以想象,这对于大数组来说可能非常慢,而且在经常使用时(可能在循环中,等等),甚至对于较小的数组,也可能是一个性能问题。
那么有没有办法加快速度呢?
在最好的情况下,我们可以“成批“”移动”数据(就像System.Move
方法一样),而不是一个一个地设置。但是由于TMyType1
和TMyType2
的大小不同,我无法想象有什么方法可以处理这个问题。这意味着复制数据的“模式(阅读2个字节并只使用第一个字节)就像复制图像中的“遮罩”区域,而不是逐像素复制,这不是很好吗?)
我想了很多,并放弃了一些想法,先将数据“移动”(使用System.Move
)到一个压缩记录数组中,每个记录都包含TMyArrayType1
(和比?)的低位和高位字节,我被卡住了,所以我认为这个问题没有真实的的解决方案,现在我想知道你们中是否有人能告诉我我错了。
1条答案
按热度按时间zkure5ic1#
简单时间测量的小测试。汇编程序每轮处理4个元素。
此代码将500兆字节的字解压缩为1 GB的双字。
在内存吞吐量为12 GB/秒(Haswell Xeon 3.1 GHz,单通道DDR3-1600内存)的计算机上:调试模式exe为分配方法和asm解包提供了516/219 ms,发布模式exe为两种方法提供了约220 ms-注意7 GB/秒的处理,因此内存限制了速度(从不同地址读写小块)
在内存吞吐量为45 GB/秒(锐龙5600 G,双通道DDR4-3200)的机器上:调试模式exe为分配方法和asm解包提供227/119 ms,发布模式exe为两种方法提供108/78 ms,代码处理14/18 GB/秒,因此内存再次限制了速度。
似乎每秒7-14 GB不是真实的的瓶颈