违反 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 编织器也是如此。
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 编织器也是如此。