使用 System.Numerics.Vector 的 C# SIMD 排序/中值

标签 c# simd

我有一个视频处理代码,需要使用 4 个相邻像素的中值来确定每个像素的值。因此,我有一个 4 字节的数组,必须以一种高效的方式找到它的中位数。首先,我必须对数组进行排序,然后对两个中间值求平均值。我必须对图像的一半像素执行此操作,以便可以并行完成。

这可以使用 System.Numerics.Vector 来完成吗?

文档中也不清楚:System.Numerics.Vector 是为 x86 代码还是仅为 x64 创建 SIMD?

最佳答案

在这个答案中,我不会费心将数据放在正确的位置,而只是将业务中值获取。

我假设你有单独的左/上/右/下向量。将它们打包在一个向量中会非常烦人,而且实际上也更难设置,因为这无法通过简单的加载来完成。

您不必进行排序(这需要大量比较和条件选择)来找到 4 的中位数。找到最小值和最大值并删除它们就足够了(当然,每个都一次)。查找最小值和最大值很容易,只需应用 Vector.MinVector.Max 几次即可。 “除”是指从四项之和中减去它们。当然,由于其结果代表两个字节的总和,因此它本身无法容纳一个字节[注1],因此不幸的是大部分计算都是在16位中完成的,吞吐量减半。最后,只需将中间两个值的和右移 1 即可得到平均值,然后可以将其转换回 8 位。

或者简而言之,4 的中位数是,不排序:

median = (a + b + c + d - min(a, b, c, d) - max(a, b, c, d)) >> 1;

您可以选择在类次前加 1 以获得向上取整的平均值。

1:如果不是这样,让计算结束就可以解决所有问题。如果它是 3 的中位数,则结果适合 8 位,因此可以在不加宽的情况下完成(即使总和可能会回绕,减法也会将其“展开”相同的量) )。当然也可以用XOR来完成,这样效果就更明显了。

关于使用 System.Numerics.Vector 的 C# SIMD 排序/中值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39050526/

相关文章:

c# - 在方法的开头或结尾调用基方法?

c# - 给定一个 DateTimeZone 和两个 Instants,确定 LocalTime 是否落在两个 Instants 之间

javascript - C#'s/Java' s JQuery/JavaScript 中的 List<Type> 数据结构

从基于源的索引转换为基于目标的索引

c# - 如何阻止用户在 session 事件期间单击屏幕上的任意位置

c# - 在 Entity Framework 的Linq Select中使用自定义方法

intel - 如何读取 "Intel Intrinsics Guide"?

c++ - NEON vector 数据类型的别名

c++ - SSE 优化循环,在数组中查找零并切换标志 + 更新另一个数组

assembly - ARM NEON 代码中冒号的含义是什么