用很少的动作提高紧密循环的速度:)

时间:2016-12-21 16:27:16

标签: freepascal

我已经开始使用Lazarus,一个免费的Pascal Delphi版本。 并且...今天的计算机在一个CPU周期中处理了相当多的字节...这让我遇到了问题和疑问。

我有一个紧凑的循环,我想要向上或向下移动一部分字节,总是只有一个字节。考虑一下代码:

LowBound := 7;
HighBound := 245; // Always the last record in the array.
// Shrink the array
For x := LowBound to Highbound-1 DO ByteArray[x] := ByteArray[x+1];
SetLength(ByteArray,HIGH(ByteArray)); // Shrinks the array by one.

// Next Part as an example of my Expanding.
LowBound := 18;
HighBound := 207; // Always the last record in the array.
SetLength(ByteArray,HIGH(ByteArray)+2); // Expands the array by one.
For x := HighBound DownTo LowBound DO ByteArray[x+1] := ByteArray[x];

假设32位代码在每个CPU周期可以移位4个字节,而64位代码可以在一个CPU周期中移位8个字节,我的简单1个字节一次接近似乎根本没有效率。

也许将数组转换为Cardinal(32位)或INT64(64位)的数组然后进行一些移位/移动? 有人有这方面的想法吗? 感谢答案, 的Morten。

1 个答案:

答案 0 :(得分:1)

了解MOVE功能后

我在FOR上做了一些实验 - > DO循环与此MOVE功能。 我对Bytes的工作已经暂停,因为我还没有让我的惯例工作,所以我对红雀队的阵列进行了一些测试。

首先,我制作了两个1 000 000(100万)红衣主教的阵列。 第二,我用随机数填充第一个数组(花了不到1秒) 第三,我使用第二个数组索引此数组,因此使用第二个数组对数字进行排序。 以下是我的结果:

  1. 使用FOR - >用于转移索引的DO循环,总时间:11m33s
  2. 使用MOVE功能移动索引,总时间:2m 2s
  3. 在没有详细介绍我的排序例程的情况下,事实仍然是指数的可变部分向上移动1个位置接近1 000 000(1百万)次。使用循环执行此操作在CPU周期方面非常昂贵。

    在不断移动数据的情况下,非常值得研究MOVE功能。

    MOVE功能几乎比循环功能快6倍。

    注意:由于move-function移动指定的字节数,因此要移动的记录数必须乘以4. Cardinal = 4 bytes。

    VAR
      DataArray : ARRAY [0..100] OF Cardinal;
    
    Move(DataArray[5],DataArray[6],4); // Equals: DataArray[6] := DataArray[5];
    Move(DataArray[5],DataArray[6],(100-5)*4); // Shifts the whole array from pos 5 one position up.