我正在优化一个算法,考虑在乘加运算中使用向量而不是双精度浮点数。最接近实现的方法显然是使用Vector.dot(v1, v2); 但是,为什么我的代码运行得如此缓慢呢?
namespace ConsoleApp1 {
class Program {
public static double SIMDMultAccumulate(double[] inp1, double[] inp2) {
var simdLength = Vector<double>.Count;
var returnDouble = 0d;
// Find the max and min for each of Vector<ushort>.Count sub-arrays
var i = 0;
for (; i <= inp1.Length - simdLength; i += simdLength) {
var va = new Vector<double>(inp1, i);
var vb = new Vector<double>(inp2, i);
returnDouble += Vector.Dot(va, vb);
}
// Process any remaining elements
for (; i < inp1.Length; ++i) {
var va = new Vector<double>(inp1, i);
var vb = new Vector<double>(inp2, i);
returnDouble += Vector.Dot(va, vb);
}
return returnDouble;
}
public static double NonSIMDMultAccumulate(double[] inp1, double[] inp2) {
var returnDouble = 0d;
for (int i = 0; i < inp1.Length; i++) {
returnDouble += inp1[i] * inp2[i];
}
return returnDouble;
}
static void Main(string[] args) {
Console.WriteLine("Is hardware accelerated: " + Vector.IsHardwareAccelerated);
const int size = 24;
var inp1 = new double[size];
var inp2 = new double[size];
var random = new Random();
for (var i = 0; i < inp1.Length; i++) {
inp1[i] = random.NextDouble();
inp2[i] = random.NextDouble();
}
var sumSafe = 0d;
var sumFast = 0d;
var sw = Stopwatch.StartNew();
for (var i = 0; i < 10; i++) {
sumSafe = NonSIMDMultAccumulate(inp1, inp2);
}
Console.WriteLine("{0} Ticks", sw.Elapsed.Ticks);
sw.Restart();
for (var i = 0; i < 10; i++) {
sumFast = SIMDMultAccumulate(inp1, inp2);
}
Console.WriteLine("{0} Ticks", sw.Elapsed.Ticks);
// Assert.AreEqual(sumSafe, sumFast, 0.00000001);
}
}
}
SIMD版本与非SIMD版本相比,需要约70%的更多时钟周期。我正在运行Haswell架构,在我看来,应该实现FMA3!(发布版本,x64优先)。
有什么建议吗? 谢谢大家!
new Vector<double>(inp1, i);
的方式在主循环和剩余循环中都一样,看起来不对。另外,C#是否会优化掉Vector
的构造? - chtz