我正在寻求优化一个程序,该程序的大量计算基于大量 2D 点的旋转。我四处搜寻,看看是否可以在 C# 中使用 SIMD 进行这些计算。
我在这里找到了一个 C++ 答案,它似乎可以满足我的要求,但我似乎无法使用 System.Numerics.Vectors 包将其转换为 C#。
任何人都可以为我指明如何做到这一点的正确方向吗?
下面的代码显示了没有 SIMD 的常规方法。其中 Point 是一个具有 double X 和 Y 的结构。
public static Point[] RotatePoints(Point[] points, double cosAngle, double sinAngle)
{
var pointsLength = points.Length;
var results = new Point[pointsLength];
for (var i = 0; i < pointsLength; i++)
{
results[i].X = (points[i].X * cosAngle) - (points[i].Y * sinAngle);
results[i].Y = (points[i].X * sinAngle) + (points[i].Y * cosAngle);
}
return results;
}
编辑: 我已经成功地使用两个 Vector< float> 实现了工作,但从基准测试来看,这似乎比以前的实现慢很多。
private static void RotatePoints(float[] x, float[] y, float cosAngle, float sinAngle)
{
var chunkSize = Vector<float>.Count;
var resultX = new float[x.Length];
var resultY = new float[x.Length];
Vector<float> vectorChunk1;
Vector<float> vectorChunk2;
for (var i = 0; i < x.Length; i += chunkSize)
{
vectorChunk1 = new Vector<float>(x, i);
vectorChunk2 = new Vector<float>(y, i);
Vector.Subtract(Vector.Multiply(vectorChunk1, cosAngle), Vector.Multiply(vectorChunk2, sinAngle)).CopyTo(resultX, i);
Vector.Add(Vector.Multiply(vectorChunk1, sinAngle), Vector.Multiply(vectorChunk2, cosAngle)).CopyTo(resultY, i);
}
}
最佳答案
编辑中添加的代码是一个好的开始,但是 Vector.Multiply(Vector<float>, float)
的代码生成器非常糟糕,所以应该避免这个功能。不过,要避免这种情况,很容易进行更改,只需在循环外广播并乘以向量即可。我还添加了更合适的循环边界和“标量尾数”,以防向量大小不能整齐地划分输入数组的大小。
private static void RotatePoints(float[] x, float[] y, float cosAngle, float sinAngle)
{
var chunkSize = Vector<float>.Count;
var resultX = new float[x.Length];
var resultY = new float[x.Length];
Vector<float> vectorChunk1;
Vector<float> vectorChunk2;
Vector<float> vcosAngle = new Vector<float>(cosAngle);
Vector<float> vsinAngle = new Vector<float>(sinAngle);
int i;
for (i = 0; i + chunkSize - 1 < x.Length; i += chunkSize)
{
vectorChunk1 = new Vector<float>(x, i);
vectorChunk2 = new Vector<float>(y, i);
Vector.Subtract(Vector.Multiply(vectorChunk1, vcosAngle), Vector.Multiply(vectorChunk2, vsinAngle)).CopyTo(resultX, i);
Vector.Add(Vector.Multiply(vectorChunk1, vsinAngle), Vector.Multiply(vectorChunk2, vcosAngle)).CopyTo(resultY, i);
}
for (; i < x.Length; i++)
{
resultX[i] = x[i] * cosAngle - y[i] * sinAngle;
resultY[i] = x[i] * sinAngle + y[i] * cosAngle;
}
}
关于c# - 使用 System.Numerics.Vectors 旋转 2D 点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52882208/