【发布时间】:2017-02-03 02:56:39
【问题描述】:
我一直在尝试使用Vector 来使用硬件来并行化整数运算。有没有办法通过向量操作启用溢出检查?
一个例子是将两列(等长数组)的整数加在一起。这里c=a+b表示c[0] = a[0] + b[0]、c[1] = a[1] + b[1]等。
我想我可以这样做:
overflow[i] = b[i] >= 0 ? c[i] < a[i] : c[i] >= a[i];
但这(分支)可能比 .Net 的自动溢出检查慢,并且可能会抵消使用 Vector<T> 的性能优势。
我们还想优化我们最常用的运算:乘法、减法,以及较小程度的整数除法。
编辑:我想了更多,想出了这个,它比未经检查的向量加法慢 2.5 倍。似乎有很多额外的开销。
public Vector<int> Calc(Vector<int> a, Vector<int> b)
{
var result = a + b;
var overflowFlag = Vector.GreaterThan(b, Vector<int>.Zero) * Vector.LessThan(result,a)
+ Vector.LessThan(b,Vector<int>.Zero) * Vector.GreaterThan(result, a);
// It makes no sense to add the flags to the result, but haven't decided what to do with them yet,
// and don't want the compiler to optimise the overflow calculation away
return result + overflowFlag;
}
时序:(4k 次迭代添加一对 100k 数组)
- 正常添加:618ms
- 正常检查添加:1092ms
- 向量加法:208ms
- 矢量检查添加:536ms
【问题讨论】:
-
没有,当然你可以自己检查。有了更多的上下文,我可以给出更有针对性的建议。
-
@Harold - 我添加了更多上下文。有没有判断是否溢出的有效方法?
-
你不必分支(实际上你不能),你可以使用 ConditionalSelect。不加宽乘法很棘手,加宽很烦人,我会考虑一下。我稍后会回来更正确地回答
-
向量整数乘法相当慢,你应该更喜欢按位运算。
-
@Harold - 非常好 - 有很大帮助。
BitwiseOr(BitwiseAnd(...), BitwiseAnd(...))。从 536 毫秒降低到 343 毫秒(与未选中的 208 毫秒相比)。
标签: .net vector simd system.numerics