2017-07-10 62 views
0

建立一個有效的SIMD雙精度的Vector3在.net當我問我的機器是否有可能基於矢量<double>

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]); 
    } 
} 
+0

這是否工作? '+'和'*'似乎只有兩個項目返回'Vector '。所以試圖訪問'[2]'拋出一個'IndexOutOfRangeException'。 – Corak

+0

這取決於你的機器。它是硬件特定的。在我的機器上'Vector .Count''返回4.在你的機器上,它可能只返回2. – bradgonesurfing

+2

我已經讀了幾次這個問題,但它仍然不完全清楚你問的是什麼。爲什麼你不能使用'Vector3'?你不能用C#編寫自己的SIMD優化代碼。你有關於你發佈的代碼的具體問題?你只是想[審查](https://codereview.stackexchange.com/)? –

回答

1

有一種方式,如果你認爲你的Vector3D有大小= 16來做到這一點,這就像如果你有第4個座標。然後你可以使用Unsafe.Read < Vector <double> >(& v3d)它會將Vector3d不安全的轉換成Vector <double>。請注意,這隻有在矢量<雙>。計數爲4時纔有效! 一旦你對Vector <進行了simd操作,雙>你可以使用再Unsafe.Read <Vector3d>(&結果)將結果強制轉換回Vector3d。