SSE指令无视RAM理论带宽

本文关键字:理论 带宽 RAM 指令 SSE | 更新日期: 2023-09-27 18:18:59

我发布了一个方法检查字节[]为全零。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 ms内处理256 MB,给出94 GB/s。这可能吗?

我的DDR2内存有800mhz的频率。维基百科给出的理论最大带宽公式为800M*2*64*2 = 25gb/s

SSE指令无视RAM理论带宽

你做了带宽计算,这很好,因为它暴露了你的算法中的一个主要错误——当它到达e时循环结束,这只是输入路径的1/16。

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

你的算法的带宽是16MB/2.65 ms或6.0 GB/s(假设没有发现非零元素,因此需要扫描整个数组),大约是理论限制的一半。对于未调优的c#来说,这一点都不错,即使使用了Mono-SIMD编织器。