2009-07-22 56 views
7

Cho đến nay tôi đã sử dụng C# Mersenne Twister tìm thấy ở đây để tạo ra số ngẫu nhiên:C# Mersenne Twister số nguyên ngẫu nhiên thực hiện phát (SFMT) monte carlo mô phỏng

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

Tôi chỉ phát hiện SFMT đó là nghĩa vụ phải được gấp đôi so với ở đây nhanh:

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

Có ai có thể chỉ cho tôi tại triển khai C# của SFMT không?

Yêu cầu của tôi là tạo số nguyên giữa (và bao gồm) 0 và 2^20 (1048576).

Tôi cần làm điều này nghìn tỷ lần mỗi ngày cho mô phỏng chạy trên đồng hồ 24 giờ vì vậy tôi sẵn sàng dành hàng ngày để tinh chỉnh điều này cho sự hoàn hảo.

Hiện nay tôi đã điều chỉnh Trung tâm Vũ trụ Mersenne Twister bằng cách thêm một phương pháp mới để phù hợp với yêu cầu của tôi:

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

Sử dụng phương pháp genrand_int32() Tôi muốn tạo ra phiên bản của riêng tôi, genrand_int20(), mà tạo ra một số nguyên giữa (và bao gồm) 0 và 2^20 để lưu trên số truyền ở trên và dịch nhưng tôi không hiểu toán học. Chính xác làm thế nào tôi có thể làm điều này?

Cũng đang sử dụng uint sẽ nhanh hơn int hoặc chỉ là vấn đề số địa chỉ? Bởi vì tôi chỉ cần lên đến 1048576, tôi chỉ quan tâm đến tốc độ.

Điều này cũng sẽ chạy trên một hộp Windows Server 2003 R2 SP2 (32 bit) với .NET 2. Bộ vi xử lý là AMD Opteron 275 (4 lõi).

+0

Một số 20-bit sẽ đại diện cho khoảng 0-2^20-1 bao gồm, 2^20 yêu cầu 21 bit để đại diện (1 được theo sau bởi 20 số không) –

+1

Nifle: Đừng nhầm lẫn * dấu * của trình tạo (là độ dài của chuỗi) với một khoảng * * mà bạn muốn số ngẫu nhiên. – Joey

+0

@ Patrick cảm ơn bạn là đúng 2^20-1 là những gì tôi cần, tôi cần phải ngẫu nhiên chỉ mục vào một mảng chiều dài 2^20. – m3ntat

Trả lời

5

Những việc bạn có thể làm là tải xuống source from the link bạn đã khám phá trên Dự án mã. Giải nén nó, tải giải pháp trong Visual Studio và biên dịch nó. Điều này sẽ cung cấp cho bạn nguồn, một dll không được quản lý và tệp .lib.

Bạn có thể P/Gọi hàm trong dll này, (chỉ có 5 hàm đơn giản được xuất, trong đó bạn chỉ cần hai) hoặc bạn có thể sử dụng tệp dll, lib và SFMT này để tạo một wrapper được quản lý dll bạn có thể sử dụng trong C# mà không cần P/Invoke. Tôi chỉ thử phương pháp này và nó rất đơn giản để làm. Không có marshalling rõ ràng liên quan.

Dưới đây là cách thực hiện. Khi bạn đã tải xuống và biên soạn nguồn (bạn cần tiêu đề và tệp lib được tạo ra ngoài dll), hãy tạo dự án Thư viện lớp C++ CLR mới. Gọi nó là WrapSFMT hay gì đó. Đi các thuộc tính của dự án. Trong C++/Headompiled Headers, thay đổi thành "Not using precompiled headers." Trong thư mục Linker/General/Additional Library, nhập đường dẫn đến SFMT.lib. Bên dưới Trình liên kết/Đầu vào/Phụ thuộc bổ sung, thêm SFMT.lib. Đóng các trang thuộc tính. Sao chép SFMT.h vào thư mục dự án của bạn và đưa nó vào dự án.

Sửa WrapSFMT.h để đọc như sau:

#pragma once 
#include "SFMT.H" 

using namespace System; 

namespace WrapSFMT { 

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

Những tuyên bố các phương pháp mà sẽ được trong lớp học của bạn. Bây giờ hãy chỉnh sửa WrapSFMT.cpp để đọc:

#include "WrapSFMT.h" 

namespace WrapSFMT { 

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

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

Những phương pháp này bạn đã khai báo trong tệp tiêu đề. Tất cả những gì bạn đang làm là gọi các hàm từ SFMT.dll và C++/CLI sẽ tự động xử lý việc chuyển đổi từ không được quản lý sang quản lý. Bây giờ bạn sẽ có thể xây dựng WrapSFMT.dll và tham khảo nó trong dự án C# của bạn. Đảm bảo SFMT.dll nằm trong đường dẫn và bạn không gặp phải vấn đề gì.

+0

Tôi đã tải xuống các tệp DLL của anh ấy và cố thêm chúng làm tham chiếu đến dự án C# của tôi mà tôi nhận được: --------------------------- Microsoft Visual Studio --------------------------- Không thể thêm tham chiếu đến 'SFMTc.dll'. Hãy đảm bảo rằng tệp có thể truy cập được và đó là tệp hợp lệ hoặc thành phần COM hợp lệ. --------------------------- OK ------------------- -------- Bất kỳ ý tưởng nào? về cách sử dụng và gọi nó theo cách hiệu quả nhất từ ​​Visual Studio – m3ntat

+0

Ok tôi đã đặt DLL trong thư mục bin của mình và có mã: [DllImport ("SFMTc.dll")] static extern UInt32 gen_rand32(); Cuộc gọi này không có lỗi nhưng tất cả tôi nhận lại là 0, không bao giờ có bất kỳ số nào khác. – m3ntat

+0

Nếu bạn muốn sử dụng P/Invoke, bạn sẽ cần phải gọi hai hàm, init_gen_rand (UInt32), khởi tạo trình tạo với một hạt giống, và sau đó bạn có thể gọi gen_rand32() nhiều như bạn muốn. (nhưng bạn có lẽ không nên vượt quá thời gian của Mersenne Twister) –

0

Tôi không thực sự thấy vấn đề của bạn với tốc độ tại đây. Trên máy tính của tôi (Core 2 Duo T7200 @ 2 GHz) tạo ra một số nguyên ngẫu nhiên với MT19937 hoặc MT19937-64 mất khoảng 20 ns (trung bình, khi vẽ 50000 số). Vì vậy, đó sẽ là khoảng 4,32 × 10 (để khoảng 4 nghìn tỷ số) một ngày. Và đó là một lõi. Với Java. Vì vậy, tôi nghĩ rằng bạn có thể mong đợi hiệu suất được nhiều hơn đủ cho nhu cầu của bạn.

Để thực sự trả lời câu hỏi của bạn: Tôi không biết triển khai C# của SFMT, nhưng việc chuyển đổi mã C thành C# phải khá đơn giản. Tuy nhiên, bạn không đạt được nhiều, vì SFMT được tối ưu hóa cho SIMD và C# hiện không hỗ trợ trực tiếp.

+0

Tôi đã tính toán các yêu cầu Số ngẫu nhiên hàng ngày cho mô phỏng này để hỗ trợ doanh nghiệp ở mức 1.645.668.000.000. Mô phỏng thực hiện rất nhiều thứ khác chủ yếu là nhân ma trận vì vậy tôi không thể dành hết thời gian CPU cho việc tạo số ngẫu nhiên, rõ ràng là tôi muốn giảm thiểu từng số ngẫu nhiên càng nhiều càng tốt, do đó Câu hỏi Stackoverflow. – m3ntat

+1

Vâng, bạn vẫn có nhiều lõi và mô phỏng Monte Carlo có xu hướng khá song song.Tôi muốn nói trước tiên bạn nên tiếp tục và giải quyết vấn đề của mình và xem lại các phần riêng lẻ của giải pháp nếu chúng chứng minh là một vấn đề hiệu suất. – Joey

+0

Đối với SFMT tôi đã không nhận ra rằng, có lẽ cách tiếp cận tốt nhất của tôi là thử biên dịch phiên bản c tại đây: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/bin/dl/ dsl.cgi? SFMT: SFMT-src-1.3.3.zip và sau đó tận dụng nó từ mô phỏng carlo C# monte của tôi bằng cách nào đó. Tôi không quen thuộc với c/C++ làm thế nào để biên dịch src của họ và làm thế nào để sử dụng nó từ C#. – m3ntat

0

Có lý do nào bạn không thể biên dịch triển khai C thành DLL và gọi điều này từ mã C# của bạn không?

EDIT:

Tôi xin lỗi, nhưng tôi chỉ có một sự hiểu biết rất hạn chế về C (và thực sự C#), nhưng "Làm thế nào để tạo ra một dll C" có thể được giải đáp ở đây: http://www.kapilik.com/2007/09/17/how-to-create-a-simple-win32-dll-using-visual-c-2005/ và nhanh như thế nào có thể được kiểm tra bằng cách lược tả mã.

+0

Xin chào Patrick, tôi chưa bao giờ sử dụng c, không chắc chắn làm thế nào để làm điều này? và sử dụng từ C#, tôi có khả năng để mất nhiều hiệu suất giành chiến thắng bởi những gì tôi giả định .net hiện một số gói các cuộc gọi của tôi từ C# để DLL c cơ bản? – m3ntat

+0

Tôi đoán rằng P/Invoke lặp đi lặp lại vào mã không được quản lý sẽ chịu một chi phí hiệu suất khá lớn. – Joey

+0

Tôi vừa phát hiện ra điều này: http://www.codeproject.com/KB/DLL/SFMT_dll.aspx?msg=3130186 Tôi tự hỏi nếu nó có thể chứng minh hữu ích cho tình hình của tôi – m3ntat

0

Có lẽ this là những gì bạn đang tìm kiếm? Có danh sách một số triển khai.

Cụ thể, this one (bởi Cory Nelson) có thể hữu ích.

Các vấn đề liên quan