我们如何在 Vector256 (System.Runtime.Intrinsics.X86) 中交换字节?



我正在使用.net core 3.0中找到的新System.Runtime.Intrinsics.X86命名空间(单指令,多数据(在c#中优化高斯滤波器。

我正在使用 Vector256 来完成算法的大部分,但最后我必须做一个除法。我找到了如何从我的 Vector256 到 2 Vector256 以便能够进行除法,但我无法将其恢复为 ushort 版本以便我可以输出数据。我正在尝试使用 Avx2.PackUnsignedSaturate(vector1, vector2(,它有效地给了我一个 Vector256,但这些项目已经混合了(有点字节序,但我的每个 ushort 的个人值都在那里(

我所需要的只是在中间交换几个字节。使用常规循环(没有 SIMD(将输出中的值放回去很容易,但也浪费时间(嗯,我认为......很难说我是否不能对 SIMD 解决方案进行基准测试(

-我已经尝试在转换为字节的 Vector256 上进行洗牌。我无法实现我需要的,似乎字节移动被限制在各自的 128 位中。 - 我试过查看 MSDN,没有关于这些新功能的示例或描述,所以对于他们中的大多数人,我不知道他们在做什么 -我尝试查看英特尔指南(https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf(,虽然它们确实解释了一些东西,但我认为我需要的东西(XCHG或BSWAP也许?(在命名空间中找不到它们。

var initialVector1 = System.Runtime.Intrinsics.Vector256.Create(1, 2, 3, 4, 5, 6, 7, 8);
var initialVector2 = System.Runtime.Intrinsics.Vector256.Create(9, 10, 11, 12, 13, 14, 15, 16);
var convertedBackToUshort = Avx2.PackUnsignedSaturate(initialVector1, initialVector2);

转换后返回Ushort的内容应为: 1, 2, 3, 4,5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

但我得到: 1, 2, 3, 4,9, 10, 11, 12, 5, 6, 7, 8, 13, 14, 15, 16

使用Avx2.Shuffle(convertedBackToUshort, mask),我无法将 9 带回右侧(尝试使用几个 for 循环"暴力破解面具"但没有成功(

Avx2.PackUnsignedSaturate又名VPACKUSWB/VPACKUSDW,像许多256位操作一样,并排工作的两个128位版本,而不是像128位版本的放大版本。此页面上有一个漂亮的图像。还有跨车道洗牌,例如Avx2.Permute4x64,如果需要,您可以使用它们将块按"自然"顺序排列。这需要Vector256<UInt64>但这并不重要,只需在之前和之后重新解释您的向量即可。

打包操作与解包函数(例如Avx2.UnpackLow(配对得很好,如果您使用这些函数而不是"转换"函数,那么您应该不需要额外的排列。

使用标量循环确实效率不高,不仅因为它是标量循环,还因为向量和"一堆标量"之间的转换有开销。

这个问题还有一个更深层次的问题,因为高斯滤波器(或者一般来说,任何卷积(通常不包括除法,因此最终不需要这一步。由于您的数据是 ushort,因此您可以使用Avx2.MultiplyHigh按 0 到 1 之间的因子进行缩放,而无需执行任何复杂的操作。

最新更新