8

到目前为止,我一直在使用这里找到的 C# Mersenne Twister来生成随机数:

http://www.centerspace.net/resources.php

我刚刚发现SFMT应该是这里的两倍:

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/

谁能指出我的 SFMT 的 C# 实现

我的要求是生成(包括)0 和 2^20(1048576)之间的整数。

为了在 24 小时制上运行模拟,我每天需要做数万亿次,所以我准备花几天时间将它调整到完美。

目前,我通过添加一种新方法来调整 Center Space Mersenne Twister 以满足我的要求:

public uint Next20()
{            
    return (uint)(genrand_int32() >> 12);
}

使用genrand_int32()我想生成我自己的版本的方法genrand_int20(),生成一个介于(包括)0 和 2^20 之间的整数,以节省上面的演员表和移位,但我不懂数学。我该怎么做呢?

使用uint 会比 int 更快,还是只是可寻址数字的问题?因为我最多只需要1048576,所以我只关心速度。

这也将在带有 .NET 2 的 Windows Server 2003 R2 SP2(32 位)机器上运行。处理器是AMD Opteron 275(4 核)

4

5 回答 5

5

您可以做的是从您在 Code Project 上找到的链接下载源代码。解压缩,在 Visual Studio 中加载解决方案并进行编译。这将为您提供源代码、非托管 c dll 和 .lib 文件。

您可以 P/Invoke 此 dll 中的函数(仅导出了 5 个简单函数,您只需要其中两个),或者您可以使用此 dll、lib 和 SFMT 头文件来创建您可以使用的托管包装 dll在没有 P/Invoke 的 C# 中。我刚试过这个方法,做起来很简单。没有涉及明确的编组。

就是这样。下载并编译源代码后(除了 dll,您还需要头文件和创建的 lib 文件)创建一个新的 C++ CLR 类库项目。称之为 WrapSFMT 什么的。转到项目属性。在 C++/Precompiled Headers 下,更改为“Not using precompiled headers”。在 Linker/General/Additional Library Directories 下,输入 SFMT.lib 的路径。在链接器/输入/附加依赖项下,添加 SFMT.lib。关闭属性页。将 SFMT.h 复制到您的项目文件夹并将其包含在项目中。

编辑 WrapSFMT.h 如下:

#pragma once
#include "SFMT.H"

using namespace System;

namespace WrapSFMT {

public ref class SRandom
{
public:SRandom(UInt32);
public:UInt32 Rand32(void);
};
}

这些声明将在您的类中的方法。现在编辑 WrapSFMT.cpp 以阅读:

#include "WrapSFMT.h"

namespace WrapSFMT {

SRandom::SRandom(UInt32 seed)
{
    init_gen_rand(seed);
}

UInt32 SRandom::Rand32()
{
    return gen_rand32();
}
}

这些实现了您在头文件中声明的方法。您所做的只是从 SFMT.dll 调用函数,而 C++/CLI 会自动处理从非托管到托管的转换。现在您应该能够构建 WrapSFMT.dll 并在您的 C# 项目中引用它。确保 SFMT.dll 在路径中,您应该没有问题。

于 2009-07-22T20:08:08.273 回答
2

您可以在以下位置找到 SFMT(以及其他 RNG 算法)的 C# 实现... http://rei.to/random.html 页面和源代码注释是日文的,但您应该能够弄清楚。

您还可以在... http://translate.google.com/translate?hl=en&sl=ja&u=http://rei.to/random.html找到该页面的 Google 翻译版本(英语)

于 2011-03-24T18:41:12.733 回答
0

我在这里并没有真正看到您的速度问题。在我的机器(Core 2 Duo T7200 @ 2 GHz)上,使用 MT19937 或 MT19937-64 生成随机整数大约需要 20 ns(平均而言,绘制 50000 个数字时)。所以每天大约有 4,32 × 10 12(大约 4万亿个数字)。这是一个核心。用Java。因此,我认为您可以期望性能足以满足您的需求。

要实际回答您的问题:我不知道 SFMT 的 C# 实现,但是将 C 代码转换为 C# 应该相当简单。但是,您并没有获得太多收益,因为 SFMT 已针对 SIMD 进行了优化,而 C# 目前不直接支持这一点。

于 2009-07-22T16:30:24.047 回答
0

您是否有理由无法将 C 实现编译成 DLL 并从您的 C# 代码中调用它?

编辑:

很抱歉,我对 C(实际上是 C#)的了解非常有限,但是“如何创建 C dll”可以在这里回答:http ://www.kapilik.com/2007/09/ 17/how-to-create-a-simple-win32-dl​​l-using-visual-c-2005/以及通过分析代码可以检查多快。

于 2009-07-22T16:42:37.330 回答
0

也许就是你要找的东西?有几个实现的列表。

具体来说,这个(Cory Nelson)可能有用。

于 2009-07-22T17:50:13.357 回答