c# SIMD排序/中值使用system . numeric . vector
本文关键字:system numeric vector SIMD 排序 | 更新日期: 2023-09-27 18:03:08
我有一个视频处理代码,需要通过使用其4个相邻像素的中位数来确定每个像素的值。所以,我有一个4字节的数组,必须以一种有效的方式找到它的中位数。首先,我必须对数组进行排序,然后求中间两个值的平均值。我必须对图像的一半像素执行此操作,以便可以并行执行。
这可以用system . numeric . vector来完成吗?
这在文档中也不清楚:System.Numerics.Vector是否为x86代码或仅为x64创建SIMD ?
在这个答案中,我不打算在正确的位置获取数据,只是中位数业务。
我假设你有单独的左/上/右/下向量。将它们打包在一个矢量中会非常烦人,而且实际上更难设置,因为这无法通过简单的加载完成。
你不需要排序(这将需要大量的比较和条件选择)来找到4的中位数。找到最小值和最大值并删除它们就足够了(当然,每个都要删除一次)。求最小值和最大值很容易,只要对Vector.Min
和Vector.Max
应用几次就可以了。"移除"是指从这四件事的总和中减去它们。当然,由于结果表示两个字节的和,它不能容纳一个字节本身[注1],所以不幸的是,大多数计算都是在16位完成的,吞吐量减半。最后,只需将两个中间值的和右移1,得到它们的平均值,可以转换回8位。
或者简而言之,在不排序的情况下,4的中位数是:
median = (a + b + c + d - min(a, b, c, d) - max(a, b, c, d)) >> 1;
可以选择在移位前加1以得到一个四舍五入的平均值。
1:如果不是这样,让计算结束就能解决所有问题。如果它是median-of-3,结果将适合8位,因此它可以在不扩展的情况下完成(即使求和可能会换行,减法也会以相同的量"解开"它)。当然,它也可以用异或来完成,对于这种情况,它更明显地工作。