2014-09-24 5 views
5

में एक अरब यादृच्छिक युगल उत्पन्न करने का सबसे तेज़ तरीका मैं मोंटे-कार्लो सिमुलेशन कर रहा हूं, और वर्तमान में System.Random का उपयोग कर रहा हूं।हास्केल

import System.Random 
main = do 
    g <- newStdGen 
    let xs = randoms g :: [Double] 
    -- normally, I'd do other magic here 
    putStrLn $ show $ length $ take 10^9 xs 

दुर्भाग्य से, यह सी rand() कॉल का कुछ भी नहीं कहने के लिए एक बहुत लंबा समय लगता है, कम से कम 5x पायथन के random.random() की तुलना में धीमी,।

साथ ghc -O2 -optc-ffast-math -optc-O3

import System.Random 
main = do 
    g <- newStdGen 
    let xs = randoms h :: [Double] 
    putStrLn $ show $ length $ take (10^7) xs 

~ 8s लेता बनाम (IPython में)

import random 
%timeit len([random.random() for _ in range(10 ** 7)]) 

लेता है ~ 1.3s। मेरा लक्ष्य एक अरब है, लेकिन हास्केल उन्हें उचित समय में उत्पन्न नहीं कर सकता है।

मेरे पास एक सी ++ प्रोग्राम भी है जो rand() के साथ फ्लोट उत्पन्न करता है। यह 10^7 0.2s में नमूने करता है।

मैं हास्केल में [0-1) श्रेणी में यादृच्छिक युगल कैसे उत्पन्न कर सकता हूं?

आदर्श रूप से, प्रोग्राम जीएचसी जेनरेट करता है केवल rand() पॉज़िक्स कॉल करता है और एक सूची में एकत्रित होता है। सबसे स्वच्छ & सबसे तेज़ कोड के साथ उत्तर जीतता है। (नहीं, 1% स्पीडअप के लिए 10x कोड होने के लायक नहीं है।)

+3

जांच [System.Random.MWC] (http://hackage.haskell.org/package/mwc-random) – ErikR

+0

@ user5402 'withSystemRandom की MWC के उदाहरण का उपयोग करना। asGenST $ \ gen -> वर्दी वेक्टर जीन (10^7) '10 मिलियन युगल के 'वेक्टर' (जो अधिक कुशल होना चाहिए) उत्पन्न करने के लिए, 'System.Random.randoms' का उपयोग करते समय, मेरे कंप्यूटर पर लगभग 15 सेकंड लग गए केवल 12.5 सेकंड लिया। क्या आप वाकई पीढ़ी को तेज करेंगे? – bheklilr

+0

यह आपकी मदद कर सकता है: http://stackoverflow.com/questions/4577146/good-choice-for-fast-random- जनरेटर-in-haskell – Sibi

उत्तर

2

यहां मेर्सन है जो आश्चर्यजनक रूप से MWC से तेज़ लग रहा था और सी ++ धड़कता है हालांकि हम विभिन्न कंप्यूटरों पर हैं ;-)। यह देखना दिलचस्प है कि यह कितना समानांतर खरीदता है लेकिन मैं बेहतर काम पर वापस गया था।

{-# LANGUAGE BangPatterns #-} 
{-# OPTIONS_GHC -Wall      #-} 
{-# OPTIONS_GHC -fno-warn-name-shadowing #-} 
{-# OPTIONS_GHC -fno-warn-type-defaults #-} 

import System.Random.Mersenne.Pure64 

testUniform :: Int -> Double -> PureMT -> Double 
testUniform 0 !x _ = x 
testUniform n !x gen = 
    testUniform (n - 1) (x + y) gen' 
    where 
    (y, gen') = randomDouble gen 

n :: Int 
n = 10^7 

total :: Double 
total = testUniform n 0 (pureMT $ fromIntegral arbSeed) 

arbSeed :: Int 
arbSeed = 8 

mean :: Double 
mean = total/fromIntegral n 

main :: IO() 
main = print mean 

~/Dropbox/Private/Stochastic $ ./MersennePure +RTS -s 
0.4999607889729769 
    802,924,992 bytes allocated in the heap 
     164,240 bytes copied during GC 
      44,312 bytes maximum residency (2 sample(s)) 
      21,224 bytes maximum slop 
       1 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  1634 colls,  0 par 0.00s 0.01s  0.0000s 0.0000s 
    Gen 1   2 colls,  0 par 0.00s 0.00s  0.0001s 0.0002s 

    INIT time 0.00s ( 0.00s elapsed) 
    MUT  time 0.11s ( 0.11s elapsed) 
    GC  time 0.00s ( 0.01s elapsed) 
    EXIT time 0.00s ( 0.00s elapsed) 
    Total time 0.12s ( 0.12s elapsed) 

    %GC  time  4.2% (5.4% elapsed) 

    Alloc rate 7,336,065,126 bytes per MUT second 

    Productivity 95.7% of total user, 93.5% of total elapsed 
+0

मुझे यकीन नहीं है कि यह पाइथननट के उपयोग के मामले की तरह कम या कम है, लेकिन यह ध्यान देने योग्य है कि आप निर्माण से परहेज करके बड़ी सूची में उलझन में महत्वपूर्ण बचत कर रहे हैं। –

+0

क्षमा करें, मैं वर्तमान में संकुल को स्थापित करने में असमर्थ हूं इसलिए मैं जवाब नहीं दे सकता ... :( – PythonNut

+0

@ थॉमसएम.ड्यूबुइसन स्ट्रीम फ्यूजन स्ट्रीम नहीं करेगा ओवरहेड? – PythonNut