我正在使用 Intel Ivy Bridge CPU 并且想要使用 RDRAND 操作码(https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide)在 C# 中。
如何通过 C# 调用该 CPU 指令?我在这里看到了从 C# 执行汇编代码的示例:C# 中的 x86/x64 CPUID https://stackoverflow.com/questions/3216535/x86-x64-cpuid-in-c-sharp
但我不知道如何将它用于 RDRAND。代码不需要检查执行代码的CPU是否支持该指令。
我看过这个执行汇编字节代码的 C++ 示例,来自drng_样本 https://software.intel.com/sites/default/files/managed/c5/d8/drng_samples_0514.tgz英特尔:
int rdrand32_step (uint32_t *rand)
{
unsigned char ok;
/* rdrand edx */
asm volatile(".byte 0x0f,0xc7,0xf0; setc %1"
: "=a" (*rand), "=qm" (ok)
:
: "edx"
);
return ok;
}
如何将 C# 中执行汇编代码的示例与来自 Intel 的 C++ 代码结合起来drng
示例代码?
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
获得单个非负随机整数。根据问题,它不会尝试验证RDRAND
实际上在 CPU 上可用,但它确实处理指令存在但无法工作的情况。 (这在当前硬件上“不可能发生”,除非它被破坏,详细信息here https://stackoverflow.com/a/14443763/4137916.)
生成的程序集是可由托管 C# 代码使用的混合程序集。确保将程序集编译为 x86 或 x64,与非托管代码相同(默认情况下,项目设置为编译为“任何 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)
重载以在一次调用中获取许多随机值,以减少互操作的开销。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)