在SO上有答案會在運行時生成(非託管)彙編代碼,以便託管代碼重新調用。這非常有趣,但我建議您僅僅爲此目的使用C++/CLI,因爲它旨在簡化互操作場景。創建一個新的Visual C++ CLR類庫,並給它一個rdrandwrapper.cpp
:
#include <immintrin.h>
using namespace System;
namespace RdRandWrapper {
#pragma managed(push, off)
bool getRdRand(unsigned int* pv) {
const int max_rdrand_tries = 10;
for (int i = 0; i < max_rdrand_tries; ++i) {
if (_rdrand32_step(pv)) return true;
}
return false;
}
#pragma managed(pop)
public ref class RandomGeneratorError : Exception
{
public:
RandomGeneratorError() : Exception() {}
RandomGeneratorError(String^ message) : Exception(message) {}
};
public ref class RdRandom
{
public:
int Next() {
unsigned int v;
if (!getRdRand(&v)) {
throw gcnew RandomGeneratorError("Failed to get hardware RNG number.");
}
return v & 0x7fffffff;
}
};
}
這是隻是試圖模仿Random.Next
在得到一個非負的隨機整數一個非常裸機實現。根據這個問題,它不會試圖驗證CPU是否實際可用RDRAND
,但它確實可以處理指令存在但無法工作的情況。 (在當前硬件上這是「不可能發生的」,除非它被破壞,詳情如下here)。
生成的程序集是一個可以由託管C#代碼使用的混合程序集。確保將程序集編譯爲x86或x64,與非託管代碼相同(默認情況下,項目被設置爲「Any CPU」,由於非託管代碼只有一個特定的位,所以它將無法正常工作)。
using System;
using RdRandWrapper;
class Program {
static void Main(string[] args) {
var r = new RdRandom();
for (int i = 0; i != 10; ++i) {
Console.WriteLine(r.Next());
}
}
}
我對性能沒有任何要求,但它可能不是很好。如果你想以這種方式獲得很多隨機值,你可能需要一個Next(int[] values)
重載來在一次調用中獲得很多隨機值,以減少互操作的開銷。
考慮只使用['RNGCryptoServiceProvider'](https://msdn.microsoft.com/library/system.security.cryptography.rngcryptoserviceprovider),這對於大多數需要好於僞隨機數的目的來說應該足夠好。 –
@JeroenMostert謝謝您的評論。但我真的需要它是真正隨機的,以適應科學準確的軟件實驗的目的。我已經訂購了TrueRNGV3,但可能需要很長時間才能到達,同時我正在尋找替代品,而RDRAND似乎很有前途。 –
您不能在C#中執行特定於處理器的程序集。您可以爲它編寫一段C++代碼,並使用C++/CLI或P/Invoke進行封裝,如[在此]中所述(https://stackoverflow.com/questions/13436130/)。 –