【问题标题】:Fastest way to find if a 'ushort' is present within a Span<ushort> with SIMD?使用 SIMD 查找 Span<ushort> 中是否存在“ushort”的最快方法?
【发布时间】:2019-04-19 21:55:54
【问题描述】:

在 .NET Core 上的 C# 中,我正在寻找最快的方法来检查给定的 ushort 值是否存在于 Span&lt;ushort&gt; 范围内。天真的选项包括枚举跨度,但我强烈怀疑通过 SIMD(即 SSE 或 AVX)存在更快的单核选项。

这里最快的选择是什么? (不安全的代码是可以的)

【问题讨论】:

  • 你能用其他结构吗,比如Hashset&lt;ushort&gt;
  • 是的,SSE2 有 pcmpeqw,它允许您在线性搜索中一次检查 16 个字节。您可以像实现矢量化memchr 循环一样使用它(使用pmovmskb 获得整数结果)。 AVX2 具有相同指令的 32 字节版本。各种可能的优化包括在分支之前检查整个缓存行(将 pcmpeq 结果与 OR 结合)。我不知道 C#,但大概这是手动矢量化的一个很好的起点,如果你的编译器/运行时没有为你自动矢量化,即使你到达对齐边界等。
  • determine if a word has a byte equal to n 有个窍门,但可能不会比 SIMD 快

标签: c# performance .net-core simd


【解决方案1】:

一个基本实现(在应用诸如 Peter 在 cmets 中描述的优化之前)可能会像这样工作:

static unsafe bool ContainsUshort(Span<ushort> data, ushort val)
{
    int vecSize = Vector<ushort>.Count;
    var value = new Vector<ushort>(val);
    int i;
    fixed (ushort* ptr = &data[0])
    {
        int limit = data.Length - vecSize;
        for (i = 0; i <= limit; i += vecSize)
        {
            var d = Unsafe.ReadUnaligned<Vector<ushort>>(ptr + i);
            if (Vector.EqualsAny(d, value))
                return true;
        }
    }
    for (; i < data.Length; i++)
    {
        if (data[i] == val)
            return true;
    }
    return false;
}

这需要System.Runtime.CompilerServices.Unsafe 包进行不安全读取,否则从跨度(或数组)创建向量的效率要低得多。顺便说一句,EqualsAny 内在函数是用(v)ptest 而不是(v)pmovmskb 实现的,ptest 通常会花费更多的微操作,因此将其影响最小化相对更重要——但由于无法直接访问ptestpmovmskb 最终的“向量条件”AFAIK 仍然需要使用 Vector.EqualsAny(向量填充 0xFFFF)来完成,这有点愚蠢.. 不过它在我的机器上要快一点(经过测试,返回值将是false,因此未展开版本的稍早退出没有发挥作用)

var allSet = new Vector<ushort>(0xFFFF);
int limit = data.Length - vecSize * 2;
for (i = 0; i <= limit; i += vecSize * 2)
{
    var d0 = Unsafe.ReadUnaligned<Vector<ushort>>(ptr + i);
    var d1 = Unsafe.ReadUnaligned<Vector<ushort>>(ptr + i + vecSize);
    var eq = Vector.Equals(d0, value) | Vector.Equals(d1, value);
    if (Vector.EqualsAny(eq, allSet))
        return true;
}

【讨论】:

    猜你喜欢
    • 2016-10-31
    • 2012-04-21
    • 2023-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多