0

C++ で関数を作成し、組み込み関数を介して新しい Intel RdRand デジタル乱数ジェネレーターを利用できるようにしました。

__declspec(dllexport) int __stdcall GetRdRand32(PUINT32 pValue)
{
    return _rdrand32_step(pValue);
}

PInvoke を介して C# で使用できるようにラップしましたが、次のように正常に動作しています。

[DllImport("CppDynamicLinkLibrary.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int GetRdRand32(out UInt32 str);

私の使用例では、複数の乱数を要求することがよくありますが、おそらく一度に (要求元ごとに) 数百のオーダーにすぎません。私の質問は、とにかく C++ を使用しているため、乱数の動的配列 (またはベクトル) を返すことができる別の関数をまとめることは理にかなっているでしょうか。つまり、C++ DLL を複数回呼び出すだけでパフォーマンスが大幅に向上しますか? ? これは、最大 200 の乱数を多くのクライアントに同時に送信する可能性のあるサーバー アプリケーション上で行われるため、パフォーマンスが懸念されます。

やる価値があるとすれば、どうすればいいのでしょうか? 私は次のように考えていましたが、ベクトルを C# に取り込む方法を見つけることは簡単にパフォーマンスの問題になる可能性がありますか?

__declspec(dllexport) void __stdcall vGetRdRand32(std::vector<UINT32> &pArray)
{
    for (std::vector<UINT32>::iterator It = pArray.begin(); It != pArray.end(); It++ )
        _rdrand32_step(&(*It));
}

最後に、Marshal.Copy は後者のアプローチよりも優れているでしょうか。

4

2 に答える 2

2

それはむしろ、どれだけ速く行く必要があるかによって異なります。rdrand のパフォーマンスを最速にするには、64 ビットの rdrand を使用し、複数のスレッドでプルします。2 スレッドのプルは、同じコアの 2 つのハイパースレッドであっても、1 スレッドのプルの 2 倍の速さです。

したがって、すべてのコアのすべてのスレッドを 64 ビットで並列にプルするように設定すると、800MBytes/s に近づくことができるはずです。

これは直感に反するかもしれませんが、このパフォーマンス特性につながるオンチップ バスの並列処理から生じます。

ループ内の 1 つのスレッドは、Ivy Bridge で 70MBytes/s を取得する場合があります。

したがって、わずか 200 個の乱数の場合、呼び出しのオーバーヘッドが支配的になります。しかし、数メガバイトの場合、可能な限り高速にしたい場合は、スレッドを生成する価値があります。

于 2013-01-26T06:50:19.110 に答える
0

確かに、1回の呼び出しから200個の乱数を取得する方が、200個の異なる呼び出しから200個の乱数を取得するよりも高速です。それは何倍も速いかもしれません。しかし、ミリ秒の違いを話している可能性があります。したがって、それは行う価値がないかもしれません。数ミリ秒の違いは、アプリケーションの全体的なパフォーマンスに顕著な違いをもたらしますか?

あなたがそれをすることに決めたなら、あなたはおそらく、を台無しにしたくはvectorなく、むしろを台無しにしたいと思うでしょうUINT32[]。C#とC++の間のマーシャリングはせいぜいvector難しいでしょう。すべての実用的な目的のために、不可能です。

アレイをマーシャリングする方法の例については、さまざまなタイプのアレイのマーシャリングを参照してください。

配列をC#で割り当て、サイズとともにC++関数に渡すことをお勧めします。そうすれば、メモリの割り当てを解除することを心配する必要はありません。C ++コードで配列を割り当てて返す場合、C#コードはC++関数を呼び出してメモリの割り当てを解除する必要があります。

于 2012-11-18T03:52:28.553 に答える