是否可以基于 Vector<double> 在 .Net 中创建高效的 SIMD 双精度 Vector3
Posted
技术标签:
【中文标题】是否可以基于 Vector<double> 在 .Net 中创建高效的 SIMD 双精度 Vector3【英文标题】:Is it possible to create an efficient SIMD double precision Vector3 in .Net based on Vector<double> 【发布时间】:2017-07-10 10:08:25 【问题描述】:当我问我的机器时
System.Numerics.Vector<double>.Count
答案是4
,所以至少在我的机器上,SIMD 寄存器中有足够的位来保存 4 个双精度数字。
我已经尝试创建一个基于 System.Numerics.Vector<double>
的 Vector3 double,但我认为不可能创建一个与 System.Numerics.Vector3
具有相同形状的模型,它的性能比没有 SIMD 支持的基本 C# 代码更好。
例如我的尝试如下。我知道这是糟糕的代码。我只是想探索一下我可以用Vector<double>
做什么。
System.Numerics.Vector<double>
没有采用 N 个参数的构造函数。我明白为什么。这是因为在编译时你不知道Vector<double>
中可以容纳多少双打,所以库作者保护我不要在脚下开枪。
但是,如果我愿意冒险进行一些脚射,我可以改进以下代码吗?
using System.Numerics;
public struct Vector3Double
public readonly double X;
public readonly double Y;
public readonly double Z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector3Double(double x, double y, double z) : this()
X = x;
Y = y;
Z = z;
// Factory for SIMD Vector<double> but it is slow because
// I need to create an array on the heap to initialize
static Vector<double> vd(double x, double y, double z)
=> new Vector<double>(new []x,y,z,0);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Dot(Vector3Double a, Vector3Double b)
var s = vd( a.X, a.Y, a.Z ) * vd( b.X, b.Y, b.Z );
return s[0] + s[1] + s[2];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Double Add(Vector3Double a, Vector3Double b)
var s = vd( a.X, a.Y, a.Z ) + vd( b.X, b.Y, b.Z );
return new Vector3Double( s[0], s[1], s[2] );
【问题讨论】:
这还能用吗?+
和 *
似乎都返回了一个只有两个项目的 Vector<double>
。所以尝试访问s[2]
会抛出IndexOutOfRangeException
。
这取决于你的机器。它是特定于硬件的。在我的机器上Vector<double>.Count
返回 4。在你的机器上它可能只返回 2。
我已经读过这个问题几次,但我仍然不完全清楚你在问什么。为什么不能只使用Vector3
?您不能真正用 C# 编写自己的 SIMD 优化代码。您对发布的代码有什么具体问题?你只是想要它reviewed?
Vector3 是单精度。我想要双精度。我想知道我是否可以使用 Vector如果您认为 Vector3d 的 size=16,则有一种方法可以做到这一点,就像您有第四个坐标一样。然后您可以使用 Unsafe.Read
【讨论】:
以上是关于是否可以基于 Vector<double> 在 .Net 中创建高效的 SIMD 双精度 Vector3的主要内容,如果未能解决你的问题,请参考以下文章