C#Mersenne Twister随机整数生成器实现(SFMT)蒙特卡罗模拟

时间:2009-07-22 16:10:03

标签: c# random montecarlo

到目前为止,我一直在使用此处的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核)

5 个答案:

答案 0 :(得分:5)

您可以下载在代码项目中发现的source from the link。解压缩,在Visual Studio中加载解决方案并进行编译。这将为您提供源,非托管c dll和.lib文件。

你可以在这个dll中调用/调用函数,(只导出5个简单函数,你只需要两个)或者你可以使用这个dll,lib和SFMT头文件来创建一个托管包装器dll你可以在C#中使用没有P / Invoke。我刚试过这个方法,这很简单。没有明确的编组工作。

这是怎么回事。下载并编译 (您需要标题和除dll之外创建的lib文件)后,创建一个新的C ++ CLR类库项目。称之为WrapSFMT或其他东西。转到项目属性。在C ++ / Precompiled Headers下,更改为“Not using precompiled headers”。在“链接器/常规/附加库目录”下,输入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在路径中,您应该没有问题。

答案 1 :(得分:1)

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

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

答案 2 :(得分: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#目前不直接支持,因此您获得的收益并不高。

答案 3 :(得分:0)

有没有理由不能将C实现编译成DLL并从C#代码中调用它?

修改

对不起,但我对C(实际上是C#)知之甚少,但“如何创建C dll”可以在这里回答:http://www.kapilik.com/2007/09/17/how-to-create-a-simple-win32-dll-using-visual-c-2005/以及有多快可以通过分析代码来检查。

答案 4 :(得分:0)

也许this正是您要找的? 有几个实现的列表。

具体而言,this one(由Cory Nelson提供)可能有用。