C#SIMD使用System.Numerics.Vector排序/中位数

时间:2016-08-20 04:38:51

标签: c# simd

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

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

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

1 个答案:

答案 0 :(得分:3)

在这个答案中,我不打算把数据放在正确的位置,只是业务的中位数。

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

你不必排序(这需要大量的比较和ConditionalSelects)来找到4的中位数。找到最小值和最大值并删除它们就足够了(当然,每次一次)。找到最小值和最大值很简单,只需应用Vector.MinVector.Max几次即可。 "删除"意味着从4件事的总和中减去它们。当然,因为它的结果代表两个字节的总和,它不能适合字节本身[ note 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来完成,为此它更有效。