优化求和2个字节数组的总和

时间:2019-05-01 23:53:44

标签: c# arrays performance opencv

我正在遍历一个字节数组,并在for循环中添加另一个字节数组的值。

        var random = new Random();
        byte[] bytes = new byte[20_000_000]; 
        byte[] bytes2 = new byte[20_000_000];

        for (int i = 0; i < bytes.Length; i++)
        {
            bytes[i] = (byte)random.Next(255);
        }

        for (int i = 0; i < bytes.Length; i++)
        {
            bytes2[i] = (byte)random.Next(255);
        }

        //how to optimize the part below
        for (int i = 0; i < bytes.Length; i++)
        {
            bytes[i] += bytes2[i];
        }

有什么方法可以加快这一过程,因此它可以比线性方法更快。

3 个答案:

答案 0 :(得分:2)

您可以使用Vector

static void Add(Span<byte> dst, ReadOnlySpan<byte> src)
{
    Span<Vector<byte>> dstVec = MemoryMarshal.Cast<byte, Vector<byte>>(dst);
    ReadOnlySpan<Vector<byte>> srcVec = MemoryMarshal.Cast<byte, Vector<byte>>(src);

    for (int i = 0; i < dstVec.Length; ++i)
    {
        dstVec[i] += srcVec[i];
    }

    for (int i = dstVec.Length * Vector<byte>.Count; i < dst.Length; ++i)
    {
        dst[i] += src[i];
    }
}

如果您在此处使用指针来对齐数组之一,则会更快。

答案 1 :(得分:2)

假设您的计算机具有多个处理器/核,则可以利用所有处理器/核。

Parallel.ForEach(Partitioner.Create(0, bytes.Length), range =>
{
    for (int i = range.Item1; i < range.Item2; i++)
    {
        bytes[i] += bytes2[i];
    }
});

答案 2 :(得分:2)

将数组长度填充到8的下一个最高倍数(在您的示例中已经如此。)

使用不安全的上下文创建两个指向现有字节数组开头的ulong数组。使用for循环来迭代bytes.Length / 8次,一次添加8个字节。

在我的系统上,运行时间不到13毫秒。相比之下,原始代码为105毫秒。

您必须添加/unsafe选项才能使用此代码。打开项目属性,然后选择“允许使用不安全的代码”。

var random = new Random();
byte[] bytes = new byte[20_000_000]; 
byte[] bytes2 = new byte[20_000_000];




int Len = bytes.Length >> 3; // >>3 is the same as / 8

ulong MASK =    0x8080808080808080;
ulong MASKINV = 0x7f7f7f7f7f7f7f7f;

//Sanity check
if((bytes.Length & 7) != 0) throw new Exception("bytes.Length is not a multiple of 8");
if((bytes2.Length & 7) != 0) throw new Exception("bytes2.Length is not a multiple of 8");

unsafe
{
    //Add 8 bytes at a time, taking into account overflow between bytes
   fixed (byte* pbBytes = &bytes[0])
   fixed (byte* pbBytes2 = &bytes2[0])
   {
      ulong* pBytes = (ulong*)pbBytes;
      ulong* pBytes2 = (ulong*)pbBytes2;
      for (int i = 0; i < Len; i++)
      {
        pBytes[i] = ((pBytes2[i] & MASKINV) + (pBytes[i] & MASKINV)) ^ ((pBytes[i] ^ pBytes2[i]) & MASK);
      } 
   }
}