2009-07-22 35 views
7

Hasta ahora he estado usando el C# Mersenne Twister encontrado aquí para generar números aleatorios:C# Mersenne Twister entero aleatorio aplicación generador (SFMT) simulación de Monte Carlo

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

acabo de descubrir SFMT que es se supone que es el doble de rápido aquí:

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

¿Alguien puede indicarme una implementación de C# de SFMT?

Mis requisitos son generar un número entero entre (e incluyendo) 0 y 2^20 (1048576).

Necesito hacer esto trillones de veces todos los días para una simulación que se ejecuta en un reloj de 24 horas, así que estoy dispuesto a pasar días ajustando esto a la perfección.

Actualmente lo hemos ajustado el Centro Espacial Mersenne Twister mediante la adición de un nuevo método para adaptarse a mis necesidades:

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

Utilizando el método genrand_int32() Me gustaría producir mi propia versión, genrand_int20(), que genera una entero entre (e incluido) 0 y 2^20 para guardar en el molde anterior y cambiar pero no entiendo las matemáticas. ¿Exactamente cómo puedo hacer esto?

También está utilizando un uint va a ser más rápido que int, o es solo una cuestión de números direccionables? Como solo necesito hasta 1048576, solo me preocupa la velocidad.

También esto será ejecuta en un 2003 R2 SP2 caja (32 bits) Windows Server con .NET 2. Procesador es AMD Opteron 275 (4 core).

+0

Un número de 20 bits representará el rango de 0 a 2^20-1 incluido, 2^20 requiere 21 bits para representar (un 1 seguido de 20 ceros) –

+1

Nifle: No confunda el * período * del generador (que es la longitud de la secuencia) con un * intervalo * en el que desea números aleatorios. – Joey

+0

@Patrick gracias, está en lo correcto 2^20-1 es lo que necesito, necesito indexar aleatoriamente en una matriz de longitud 2^20. – m3ntat

Respuesta

5

Lo que puede hacer es descargar el source from the link que descubrió en Code Project. Descomprímalo, cargue la solución en Visual Studio y compílela. Esto le dará origen, un dll c no administrado y un archivo .lib.

Puede P/Invocar las funciones en este dll, (solo hay 5 funciones simples exportadas, de las cuales solo necesita dos) o puede usar este dll, lib y el archivo de encabezado SFMT para crear un contenedor administrado dll puede usar en C# sin P/invocar. Acabo de probar este método y fue muy simple de hacer. No hubo una clasificación explícita involucrada.

He aquí cómo. Una vez que haya descargado y compilado el fuente (necesita el encabezado y el archivo lib que se crea además del dll), cree un nuevo proyecto de Biblioteca de clases CLR de C++. Llámalo WrapSFMT o algo así. Ir a las propiedades del proyecto. En C++/Encabezados precompilados, cambie a "No usar encabezados precompilados". En Linker/General/Additional Library Directories, ingrese la ruta a SFMT.lib. En Enlazador/Entrada/Dependencias adicionales, agregue SFMT.lib. Cierre las páginas de propiedades. Copie SFMT.h a su carpeta de proyecto e inclúyalo en el proyecto.

Editar WrapSFMT.h para que lea como sigue:

#pragma once 
#include "SFMT.H" 

using namespace System; 

namespace WrapSFMT { 

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

Estos declaran los métodos que serán en su clase. Ahora edite WrapSFMT.cpp para que lea:

#include "WrapSFMT.h" 

namespace WrapSFMT { 

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

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

Implementan los métodos que declaró en el archivo de encabezado. Todo lo que hace es llamar funciones desde SFMT.dll, y C++/CLI maneja automáticamente la conversión de no gestionada a administrada. Ahora debería poder compilar WrapSFMT.dll y referenciarlo en su proyecto C#. Asegúrese de que SFMT.dll esté en la ruta y no debería tener problemas.

+0

Descargué sus archivos DLL e intenté agregarlos como referencia para mi proyecto C# Obtengo: --------------------------- Microsoft Visual Studio --------------------------- No se pudo agregar una referencia a 'SFMTc.dll'. Asegúrese de que el archivo esté accesible y de que sea un ensamblaje o componente COM válido. --------------------------- OK ------------------- -------- ¿Alguna idea? sobre cómo usar esto y llamarlo de la manera más eficiente desde Visual Studio – m3ntat

+0

Ok, he colocado el archivo DLL en mi carpeta bin, y tengo código: [DllImport ("SFMTc.dll")] static extern UInt32 gen_rand32(); Esta llamada sin errores pero todo lo que obtengo es 0, nunca ningún otro número. – m3ntat

+0

Si desea utilizar P/Invoke, necesitará invocar dos funciones, init_gen_rand (UInt32), inicializando el generador con un seed, y luego puede llamar a gen_rand32() tanto como desee. (pero probablemente no deberías exceder el período del Twister de Mersenne) –

0

Realmente no veo su problema con la velocidad aquí. En mi máquina (Core 2 Duo T7200 @ 2 GHz) generar un entero aleatorio con MT19937 o MT19937-64 toma alrededor de 20 ns (en promedio, cuando se dibujan 50000 números). Eso sería alrededor de 4,32 × 10 (alrededor de 4 trillones números) al día. Y eso es por un núcleo. Con Java. Por lo tanto, creo que puede esperar que el rendimiento sea más que adecuado para sus necesidades.

Para responder realmente a su pregunta: No sé de una implementación C# de SFMT, pero la conversión del código C a C# debería ser bastante sencilla. Sin embargo, no está ganando mucho, ya que SFMT está optimizado para SIMD y C# actualmente no es compatible con esto directamente.

+0

He calculado los requisitos diarios de Número aleatorio para esta simulación para admitir el negocio en 1,645,668,000,000. La simulación hace muchas otras cosas, principalmente la multiplicación de matrices, así que no puedo dedicar todo el tiempo de CPU a la generación de números aleatorios, obviamente quiero minimizar cada gen de números aleatorios tanto como sea posible, de ahí la Pregunta de Stackoverflow. – m3ntat

+1

Bueno, todavía tienes varios núcleos y las simulaciones de Monte Carlo tienden a ser bastante paralelables.Diría que primero debe resolver su problema y revisar las partes individuales de la solución si demuestran ser un problema de rendimiento. – Joey

+0

Para SFMT no me di cuenta, tal vez mi mejor enfoque es intentar compilar la versión c aquí: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/bin/dl/ dl.cgi? SFMT: SFMT-src-1.3.3.zip y luego hacer uso de mi simulación C# monte carlo de alguna manera. No estoy familiarizado con c/C++ cómo compilar su src y cómo usarlo desde C#. – m3ntat

0

¿Hay alguna razón por la que no pueda compilar la implementación de C en una DLL y llamar esto desde su código de C#?

EDIT:

Lo siento, pero tengo sólo un conocimiento muy limitado de C (y de hecho C#), pero el "Cómo crear un archivo DLL C" puede ser contestada aquí: http://www.kapilik.com/2007/09/17/how-to-create-a-simple-win32-dll-using-visual-c-2005/ y la rapidez se puede comprobar mediante el perfil del código.

+0

Hola Patrick, nunca he usado c, no estoy seguro de cómo hacer esto? y el uso de C#, ¿es probable que pierda mucho rendimiento gana por lo que asumo .net hace un ajuste de mis llamadas de C# a la DLL c subyacente? – m3ntat

+0

Supongo que P/Invocar repetidamente en código no administrado incurre en una sobrecarga de rendimiento bastante considerable. – Joey

+0

Acabo de descubrir esto: http://www.codeproject.com/KB/DLL/SFMT_dll.aspx?msg=3130186 me pregunto si podría ser útil para mi situación – m3ntat

0

¿Tal vez this es lo que estás buscando? Hay una lista de varias implementaciones.

Específicamente, this one (por Cory Nelson) puede ser útil.

Cuestiones relacionadas