So far I've been using the C# Mersenne Twister found here to generate random numbers:
http://www.centerspace.net/resources.php
I just discovered SFMT which is supposed to be twice as fast here:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
Can anyone point me at a C# implementation of SFMT?
My requirements are to generate an integer between (and including) 0 and 2^20 (1048576).
I need to do this trillions of times everyday for a simulation running on a 24 hour clock so I am prepared to spend days tweaking this to perfection.
Currently I've tweaked the Center Space Mersenne Twister by adding a new method to fit my requirements:
public uint Next20()
{
return (uint)(genrand_int32() >> 12);
}
Using the method genrand_int32()
I'd like to produce my own version, genrand_int20()
, that generates an integer between (and including) 0 and 2^20 to save on the cast above and shift but I don't understand the mathematics. Exactly how can I do this?
Also is using an uint going to be faster that int, or is just a matter of addressable numbers? Because I only need up to 1048576, I am only concerned with speed.
Also this will be running on a Windows Server 2003 R2 SP2 (32bit) box with .NET 2. Processor is AMD Opteron 275 (4 core).
What you can do is download the source from the link you discovered on Code Project. Unzip it, load the solution in Visual Studio and compile it. This will give you source, an unmanaged c dll and a .lib file.
You can P/Invoke the functions in this dll, (there are only 5 simple functions exported, of which you need only two) or you can use this dll, lib, and the SFMT header file to create a managed wrapper dll you can use in C# without P/Invoke. I just tried this method and it was very simple to do. There was no explicit marshalling involved.
Here's how. Once you have downloaded and compiled the source (you need the header and the lib file that is created in addition to the dll) create a new C++ CLR Class Library project. Call it WrapSFMT or something. Go the project properties. Under C++/Precompiled Headers, change to "Not using precompiled headers." Under the Linker/General/Additional Library Directories, enter the path to the SFMT.lib. Under Linker/Input/Additional Dependencies, add SFMT.lib. Close the property pages. Copy SFMT.h to your project folder and include it in the project.
Edit WrapSFMT.h to read as follows:
#pragma once
#include "SFMT.H"
using namespace System;
namespace WrapSFMT {
public ref class SRandom
{
public:SRandom(UInt32);
public:UInt32 Rand32(void);
};
}
These declare the methods that will be in your class. Now edit WrapSFMT.cpp to read:
#include "WrapSFMT.h"
namespace WrapSFMT {
SRandom::SRandom(UInt32 seed)
{
init_gen_rand(seed);
}
UInt32 SRandom::Rand32()
{
return gen_rand32();
}
}
These implement the methods you declared in the header file. All you are doing is calling functions from the SFMT.dll, and C++/CLI is automatically handling the conversion from unmanaged to managed. Now you should be able to build the WrapSFMT.dll and reference it in your C# project. Make sure the SFMT.dll is in the path, and you should have no problems.