我的任务是使用 SIMD 加速中值滤波器。我找到了一个对向量元素进行排序的教程。然而,在这个例子中,向量的元素是成对交换的。然而,我还没有找到 System.Numerics.Vector 类的命令。 是否有一种有效的方法对此类向量的元素进行排序,或者使用 SIMD 实现中值滤波器的另一种高效 C# 实现? 预先感谢您!
我在下面发现了一个很有前途的视频 https://www.youtube.com/watch?v=qejTqnxQRcw
因此我开始熟悉 System.Numerics.Vector 的基本概念,例如复制数据以及最小和最大等基本操作。然而,对于视频中的方法,也需要交换操作,但我在 System.Numerics.Vector 类的文档中找不到该操作。
System.Numerics.Vector 级别太高。 .NET 中的低级 SIMD 指令在固定大小类型
Vector128
和 Vector256
上运行
这是一个 PC 平台的示例,它对存储在 16 字节向量中的 FP32 元素进行排序。该算法被称为“排序网络”,维基百科有一个很好的插图。
static Vector128<float> sortLanes( Vector128<float> x )
{
// Flip high + low halves, with _MM_SHUFFLE( 1, 0, 3, 2 )
var tmp = Sse.Shuffle( x, x, 0x4E );
// Sort and blend
var i = Sse.Min( x, tmp );
var ax = Sse.Max( x, tmp );
x = Sse41.Blend( i, ax, 0b1100 );
// Flip even / odd lanes, with _MM_SHUFFLE( 2, 3, 0, 1 )
tmp = Sse.Shuffle( x, x, 0xB1 );
// Sort and blend
i = Sse.Min( x, tmp );
ax = Sse.Max( x, tmp );
x = Sse41.Blend( i, ax, 0b1010 );
// Sorting two lanes in the middle, _MM_SHUFFLE( 3, 1, 2, 0 )
tmp = Sse.Shuffle( x, x, 0xD8 );
// Sort and blend
i = Sse.Min( x, tmp );
ax = Sse.Max( x, tmp );
return Sse41.Blend( i, ax, 0b1100 );
}
从 .NET 7.0 开始,提供了
Vector128.Shuffle
和 Vector128.Shuffle
方法,可用于交换元素。
但Vector还是没有提供Shuffle方法。
我编写了 VectorTraits 库。该库提供了 Vectors.Shuffle 方法。它支持 Vector 的交换元素。 它支持X86和Arm平台上的硬件加速,并且支持较低版本的
.NET
程序(.NET Core 3.0
+,.NET 5.0
+...)。