我们如何交换 Vector256 (System.Runtime.Intrinsics.X86) 中的字节?
How can we swap byte in a 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);
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, 6, 7, 8, 13, 14, 15, 16
使用 Avx2.Shuffle(convertedBackToUshort, mask)
,我无法将 9 带回右侧(尝试使用几个 for 循环到 "brute-force the mask" 但没有成功)
Avx2.PackUnsignedSaturate
又名 VPACKUSWB/VPACKUSDW,与许多 256 位操作一样,工作方式类似于并排操作的两个 128 位版本,而不是 128 位版本的放大版本。有一张不错的图片 on this page。也有跨车道洗牌,例如 Avx2.Permute4x64
,如果需要,您可以使用它来将方块按 "natural" 顺序排列。它需要 Vector256<UInt64>
但这没关系,只需重新解释前后的向量即可。
打包操作与解包函数(例如 Avx2.UnpackLow
)配合得很好,如果您使用这些函数而不是 "convert" 函数,那么您不需要额外的排列。
使用标量循环确实效率不高,不仅因为它是一个标量循环,还因为在向量和 "bunch of scalars" 之间进行转换会产生开销。
这个问题还有一个更深层次的问题,因为高斯滤波器(或者一般意义上的任何卷积)通常不包含除法,因此最终不需要这一步。由于您的数据是 ushorts,您可以使用 Avx2.MultiplyHigh
以 0 到 1 之间的因子进行缩放,而无需执行任何复杂的操作。
我正在使用 .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, 6, 7, 8, 13, 14, 15, 16
使用 Avx2.Shuffle(convertedBackToUshort, mask)
,我无法将 9 带回右侧(尝试使用几个 for 循环到 "brute-force the mask" 但没有成功)
Avx2.PackUnsignedSaturate
又名 VPACKUSWB/VPACKUSDW,与许多 256 位操作一样,工作方式类似于并排操作的两个 128 位版本,而不是 128 位版本的放大版本。有一张不错的图片 on this page。也有跨车道洗牌,例如 Avx2.Permute4x64
,如果需要,您可以使用它来将方块按 "natural" 顺序排列。它需要 Vector256<UInt64>
但这没关系,只需重新解释前后的向量即可。
打包操作与解包函数(例如 Avx2.UnpackLow
)配合得很好,如果您使用这些函数而不是 "convert" 函数,那么您不需要额外的排列。
使用标量循环确实效率不高,不仅因为它是一个标量循环,还因为在向量和 "bunch of scalars" 之间进行转换会产生开销。
这个问题还有一个更深层次的问题,因为高斯滤波器(或者一般意义上的任何卷积)通常不包含除法,因此最终不需要这一步。由于您的数据是 ushorts,您可以使用 Avx2.MultiplyHigh
以 0 到 1 之间的因子进行缩放,而无需执行任何复杂的操作。