违反 RAM 理论带宽的 SSE 指令

SSE instructions defying RAM theoretical bandwidth

一种检查 byte[] 是否全为零的方法。 Mono.Simd 提供如此高的性能,我想知道这是否可能。

static unsafe bool IsAllZeros(byte[] data)
{
    fixed (byte* bytes = data) {
        int len = data.Length;
        int rem = len % (16*16);
        Vector16b* b = (Vector16b*)bytes;
        Vector16b* e = b + len / (16*16);
        Vector16b zero = Vector16b.Zero;

        while (b < e) {
            if ((*(b)|*(b+1)|*(b+2)|*(b+3)|*(b+4)|*(b+5)|*(b+6)|*(b+7)|*(b+8)|
             *(b+9)|*(b+10)|*(b+11)|*(b+12)|*(b+13)|*(b+14)|*(b+15)) != zero)
                return false;
            b += 16;
        }

        for (int i = 0; i < rem; i++)
            if (data [len - 1 - i] != 0)
                return false;

        return true;
    }
}

上面的代码在 2,6477 毫秒内处理了 256 MB,得到 94 GB/s。 这可能吗?

我的 DDR2 内存频率为 800 Mhz。 Wikipedia给出理论最大带宽的公式为800M*2*64*2 = 25 GB/s.

很高兴您进行了带宽计算,因为它暴露了您算法中的一个主要错误——循环在到达 e 时结束,这仅是输入的 1/16。

您系统中的实际最大理论带宽略小于 12.8 GB/s(DDR2/6400 额定值,乘以两个通道,减去 DRAM 忙于刷新的几个周期'被访问)。这与您问题中的计算不同,因为您对 DDR 使用了两倍的因子,并将其应用于已经包含该因子的数字。

您算法的带宽为每 2.65 毫秒 16MB 或 6.0 GB/s(假设没有找到非零元素,因此需要扫描整个数组),大约是理论限制的一半。对于未调优的 C# 来说一点也不差,即使使用 Mono-SIMD 编织器也是如此。