2017-06-07 14 views
0

SSE組み込み関数を使用せずに乗算演算を実装したC#の行列構造体を使用しています。私はこの時点でコードにアクセスすることができないので、定義をコピー/ペーストするのではなく、できるだけ詳細を指定しようとします。必要に応じて関連定義を含めるために午前中に投稿を編集することができます。Mono C#/ C++ Interop、最適化行列乗算 - オーバーヘッドによる最小限のゲイン?

構造体は、16の float sが指定されたシーケンシャルなレイアウトで M11, M12, M13, ..., M43, M44'として定義されてい

[StructLayout(LayoutKind.Sequential)] C++関数は属性指定 [DllImport("cppCode.dll", EntryPoint = "MatrixMultiply", CallingConvention = CallingConvention::Cdecl]

私はCへの呼び出しを行うためにしようとしていると宣言されている

++乗算を最適化するためにP/Invokeを使用する関数。私の質問は、パラメータを渡すことです。 MSDNで述べたように、渡された型がblittableでない場合、コストはCPU +マーシャリングの10〜30サイクルです。

のC#の関数呼び出しは

MatrixMultiply(ref matrix1, ref matrix2, out matrix_out); 

のように見えるとC++の相手はmatが4倍vec4 sの一致するC++の構造体であることで、mat*でそれらを受け取ります。

static extern void MatrixMultiply(mat* m1, mat* m2, mat* out) { *out = *m1 * *m2; } 

計算がプロファイリングされるとき、ゲインは平均で非常に小さい - マイクロ秒または2 - です。しかし、最悪のケースは、C#の乗算による150usからC++の乗算による400usへと悪化しました。これは、エクスポートされたdllから関数を呼び出すためのオーバーヘッドがSSE命令からの利益をほとんど排除すると考えるようになります。

私はC#に精通していないため、何が起こっているのかを確かめることはできません。私は何か間違っているのですか?この特定のケースでは、C#/ C++通信の方が速いアプローチですか?

+1

SIMDを利用する['System.Numerics.Vectors'](https://msdn.microsoft.com/en-us/library/dn858218(v=11111).aspx)の型を使用できます。 Matrix4x4クラスもあります。 – cubrr

+0

[構造体、私の意味](https://msdn.microsoft.com/en-us/library/system.numerics.matrix4x4(v =対111).aspx) – cubrr

+0

パフォーマンスがP/Invokeを使用しない#1の懸念事項。 C++/CLIがより適しているかもしれません(または@cubrrで提案されている組み込み型を使用) –

答えて

0

Numericsが十分な解決策を提供しない場合は、p/Invoke呼び出しを最小限に抑えることが最善の方法です。複数の呼び出しを行うのオーバーヘッドを削減する

void MatrixConcat3(m1, m2, m3, m_out); 
void MatrixConcat4(m1, m2, m3, m4, m_out); 
void MatrixConcat5(m1, m2, m3, m4, m5, m_out); 
... 

:代わりに、すべての乗算にMultiply(m1, m2, m_out)を呼び出すのでは、このような可能C++側での1回の呼び出しで行列を連結してみてください。