gpt4 book ai didi

c# - 检查字节数组是否为零的 SSE 指令 C#

转载 作者:行者123 更新时间:2023-11-30 14:27:16 25 4
gpt4 key购买 nike

假设我有一个 byte[] 并想检查所有字节是否为零。 For 循环是一种显而易见的方法,LINQ All() 是一种奇特的方法,但最高性能至关重要。

如何使用 Mono.Simd加快检查字节数组是否全为零?我正在寻找前沿方法,而不仅仅是正确的解决方案。

最佳答案

最佳代码如下。 full source 中提供了其他方法和时间测量.

static unsafe bool BySimdUnrolled (byte[] data)
{
fixed (byte* bytes = data) {
int len = data.Length;
int rem = len % (16 * 16);
Vector16b* b = (Vector16b*)bytes;
Vector16b* e = (Vector16b*)(bytes + len - rem);
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;
}
}

最终还是被这段代码打败了:

static unsafe bool ByFixedLongUnrolled (byte[] data)
{
fixed (byte* bytes = data) {
int len = data.Length;
int rem = len % (sizeof(long) * 16);
long* b = (long*)bytes;
long* e = (long*)(bytes + len - rem);

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)) != 0)
return false;
b += 16;
}

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

return true;
}
}

时间测量(在 256MB 阵列上):

LINQ All(b => b == 0)                   : 6350,4185 ms
Foreach over byte[] : 580,4394 ms
For with byte[].Length property : 809,7283 ms
For with Length in local variable : 407,2158 ms
For unrolled 16 times : 334,8038 ms
For fixed byte* : 272,386 ms
For fixed byte* unrolled 16 times : 141,2775 ms
For fixed long* : 52,0284 ms
For fixed long* unrolled 16 times : 25,9794 ms
SIMD Vector16b equals Vector16b.Zero : 56,9328 ms
SIMD Vector16b also unrolled 16 times : 32,6358 ms

结论:

  • Mono.Simd只有一组有限的指令。我没有找到计算标量和(向量)或最大值(向量)的说明。然而,向量相等运算符返回 bool。
  • 循环展开是一项强大的技术。即使是最快的代码也会从使用它中获益良多。
  • LINQ 非常慢,因为它使用来自 lambda 表达式的委托(delegate)。如果您需要尖端性能,那么显然这不是正确的选择。
  • 介绍的所有方法都使用 short circuit evaluation ,这意味着它们一遇到非零值就结束。
  • SIMD 代码最终被击败。 SO 上还有其他问题在争论 SIMD 是否真的让事情变得更快。

Posted this code在同行评审中,到目前为止发现并修复了 2 个错误。

关于c# - 检查字节数组是否为零的 SSE 指令 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33294580/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com