我正在.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);
convertedBackToUshort的内容应为: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,5,6,7,8, 13,14,15,16
使用Avx2.Shuffle(convertedBackToUshort, mask)
,我无法将9重新带回右侧(尝试使用多个for循环来“强行将面罩强行拉开”)
Avx2.PackUnsignedSaturate
aka VPACKUSWB / VPACKUSDW,就像许多256位操作一样,可以并排使用两个128位版本的操作,而不是像128位版本的放大版本。有一个漂亮的图像on this page。也有跨车道洗牌,例如Avx2.Permute4x64
,您可以根据需要将其按“自然”顺序放置。它需要一个Vector256<UInt64>
,但这并不重要,只需在前后前后重新解释向量即可。使用标量循环确实不会高效,这不仅是因为它是一个标量循环,而且还因为在向量和“标量束”之间进行转换会产生开销。
此问题中存在一个更深层次的问题,因为高斯滤波器(或实际上通常是任何卷积)通常不包含除法运算,因此最终不需要此步骤。由于您的数据是超短裤,因此您可以使用Avx2.MultiplyHigh
缩放0到1之间的倍数,而无需执行任何复杂的操作。