CUDA

2009-05-08 21 views
14

में यादृच्छिक संख्या जनरेटर मैंने पूरे दिन इस पर संघर्ष किया है, मैं अपने CUDA कोड में धागे के लिए यादृच्छिक संख्या जनरेटर प्राप्त करने का प्रयास कर रहा हूं। मैंने सभी मंचों को देखा है और हां यह विषय काफी हद तक आता है लेकिन मैंने बिना किसी लाभ के सभी प्रकार के कोडों को सुलझाने का प्रयास किया है। यदि कोई साधारण विधि के बारे में जानता है, तो शायद डिवाइस कर्नेल जिसे 0 और 1 के बीच एक यादृच्छिक फ्लोट लौटाया जा सकता है, या एक पूर्णांक जिसे मैं बदल सकता हूं, मैं सबसे आभारी हूं।CUDA

फिर से, मुझे कर्नेल में यादृच्छिक संख्या का उपयोग करने की उम्मीद है, उदाहरण के लिए रैंड() की तरह।

अग्रिम

+0

कुछ उपयोगी जानकारी: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch37.html – Jesper

उत्तर

5

धन्यवाद मुझे यकीन है कि मुझे समझ में क्यों तुम कुछ भी विशेष आवश्यकता नहीं हूँ। किसी भी पारंपरिक पीआरएनजी को कम से कम सीधे पोर्ट करना चाहिए। एक linear congruential ठीक काम करना चाहिए। क्या आपके पास कुछ विशेष गुण हैं जिन्हें आप स्थापित करने की कोशिश कर रहे हैं?

+0

मैं वह एक पुस्तकालय वह इसे खुद को लागू करने के लिए नहीं, कह सकते हैं की तलाश में लगता है। एक समाधान के लिए उसे इंगित करने के लिए अभी भी एक अच्छा जवाब है। – lothar

+0

रैखिक congruential लागू करने के लिए बहुत आसान है। आप प्रत्येक थ्रेड में अपने स्वयं के राज्य के साथ एक अलग पीआरएनजी करके CUDA के साथ ऐसा कर सकते हैं। –

+0

Thats मुझे थोड़ा उलझन में मिला। प्रत्येक थ्रेड कहता है कि इसकी थ्रेड आईडी से बीज किया जाए, लेकिन क्या वे जल्द ही ओवरलैपिंग शुरू नहीं करेंगे? – zenna

2

एक एमडीजीपीयू पैकेज (जीपीएल) है जिसमें सीयूडीए here के लिए जीएनयू रैंड 48() फ़ंक्शन का कार्यान्वयन शामिल है।

मुझे यह पता चला (Google आसानी से, Google का उपयोग करके, जो मुझे लगता है कि आपने कोशिश की :-) एनवीडिया फ़ोरम here पर।

+0

हाँ मैंने उसे भी पाया .. लेकिन मैं जो करना चाहता हूं उसे करने के लिए संघर्ष कर रहा था .. मुझे लगता है कि मुझे सिर्फ एक बेवकूफ दिन है .. मैं इसे फिर से देखूंगा, धन्यवाद – zenna

+0

एनवीडिया में टिप्पणियों के मुताबिक फोरम (लेखक सहित) कार्यान्वयन अच्छी तरह से काम नहीं करता है। –

2

मैं CUDA के लिए एक अच्छा समानांतर संख्या जनक नहीं मिला है, लेकिन मैं यहाँ शैक्षिक अनुसंधान के आधार पर एक समानांतर यादृच्छिक संख्या जनरेटर मिला: http://sprng.cs.fsu.edu/

+0

किसी को भी इस एल्गोरिदम के CUDA संस्करण के बारे में पता है? –

+0

"अच्छा" से आपका क्या मतलब है? आपकी आवश्यकताओं के आधार पर एक साधारण एमडी 5 हैश (सीयूडीपीपी देखें) पर्याप्त हो सकता है। कुछ मामलों के लिए, कई मेर्सन ट्विस्टर सबसे अच्छे हो सकते हैं क्योंकि उनके पास वास्तव में लंबी अवधि और धाराओं के बीच अच्छी आजादी है। एनएजी में एल इक्वायर का एमआरजी 32 के 3 ए है जो वास्तव में अच्छी तरह से काम करता है यदि आपको एकाधिक धागे/ब्लॉक में एक एकल स्ट्रीम की आवश्यकता है। – Tom

+0

एक अच्छी शुरुआत एक दोहराव वाले छद्म-यादृच्छिक संख्या जनरेटर होगी जो कोशिकाओं के बीच कम निर्भरता के साथ - उपयुक्त, यादृच्छिक संख्या सरणी का एक सेट बनाने के लिए, प्रत्येक सरणी की सामग्री को कई धागे से भरकर, लेकिन एक के बाद एक सरणी बनाना होगा। –

4

आपके आवेदन के आधार पर आप पर विचार किए बिना LCGs का उपयोग कर से सावधान रहना चाहिए चाहे धाराएं (प्रति थ्रेड एक स्ट्रीम) ओवरलैप हो जाएंगी। आप एलसीजी के साथ एक लीपफ्रॉग लागू कर सकते हैं, लेकिन फिर यह सुनिश्चित करने के लिए कि अनुक्रम दोहराना नहीं है, आपको पर्याप्त लंबी अवधि एलसीजी की आवश्यकता होगी।

एक उदाहरण मेंढक कूद हो सकता है:

template <typename ValueType> 
__device__ void leapfrog(unsigned long &a, unsigned long &c, int leap) 
{ 
    unsigned long an = a; 
    for (int i = 1 ; i < leap ; i++) 
     an *= a; 
    c = c * ((an - 1)/(a - 1)); 
    a = an; 
} 

template <typename ValueType> 
__device__ ValueType quickrand(unsigned long &seed, const unsigned long a, const unsigned long c) 
{ 
    seed = seed * a; 
    return seed; 
} 

template <typename ValueType> 
__global__ void mykernel(
    unsigned long *d_seeds) 
{ 
    // RNG parameters 
    unsigned long a = 1664525L; 
    unsigned long c = 1013904223L; 
    unsigned long ainit = a; 
    unsigned long cinit = c; 
    unsigned long seed; 

    // Generate local seed 
    seed = d_seeds[bid]; 
    leapfrog<ValueType>(ainit, cinit, tid); 
    quickrand<ValueType>(seed, ainit, cinit); 
    leapfrog<ValueType>(a, c, blockDim.x); 

    ... 
} 

लेकिन तब कि जनरेटर की अवधि शायद ज्यादातर मामलों में अपर्याप्त है।

ईमानदार होने के लिए, मैं NAG जैसे किसी तृतीय पक्ष लाइब्रेरी का उपयोग करना चाहता हूं। एसडीके में कुछ बैच जनरेटर भी हैं, लेकिन शायद यह नहीं है कि आप इस मामले में क्या खोज रहे हैं।

संपादित

के बाद से यह सिर्फ कर ली ऊपर वोट दिया है, मैं समझ यह है कि cuRAND, के रूप में इस सवाल का अधिक हाल ही में उत्तर से उल्लेख किया है, उपलब्ध है उल्लेख करने के लिए अद्यतन करने के लायक है और जनरेटर और वितरण के एक नंबर प्रदान करता है। यह निश्चित रूप से शुरू करने का सबसे आसान स्थान है।

9

रुचि रखने वाले किसी भी व्यक्ति के लिए, अब आप इसे cuRAND के माध्यम से कर सकते हैं।

4

इस के लिए सबसे अच्छा तरीका है अपने स्वयं के डिवाइस समारोह लिख रहा है, यहाँ एक

void RNG() 
{ 
    unsigned int m_w = 150; 
    unsigned int m_z = 40; 

    for(int i=0; i < 100; i++) 
    { 
     m_z = 36969 * (m_z & 65535) + (m_z >> 16); 
     m_w = 18000 * (m_w & 65535) + (m_w >> 16); 

     cout <<(m_z << 16) + m_w << endl; /* 32-bit result */ 
    } 
} 

यह आप 32 बिट परिणाम के साथ 100 यादृच्छिक नंबर देंगे है।

आप 1 और 1000 के बीच कुछ यादृच्छिक संख्या चाहते हैं, आप भी result%1000 ले जा सकते हैं, या तो खपत के बिंदु पर, या पीढ़ी के बिंदु पर:

((m_z << 16) + m_w)%1000 

m_w और m_z शुरू करने मूल्यों में परिवर्तन करना (उदाहरण में, 150 और 40) आपको प्रत्येक बार एक अलग परिणाम प्राप्त करने की अनुमति देता है। आप threadIdx.x का उपयोग उन में से एक के रूप में कर सकते हैं, जो आपको हर बार अलग छद्म यादृच्छिक श्रृंखला देना चाहिए।

मैं जोड़ने के लिए है कि यह 2 समय तेजी से काम करता है रैंड() फ़ंक्शन से, और अच्छा काम करता है चाहता था;)

+3

संपादक की टिप्पणी: यह एक साफ छोटा आरएनजी है, लेकिन यह कहीं भी गणना के लिए उपयोग करने योग्य नहीं है जहां अच्छी यादृच्छिक संख्या की आवश्यकता होती है। इसमें 2^16 की अवधि है, यह पूरे 32 बिट नंबर स्पेस को नहीं बढ़ा सकता है, और यह एक साधारण चरण और छोटी अवधि के कारण काफी आसानी से उलट है। – qdot

4

मुझे लगता है कि इस सवाल का किसी भी चर्चा Zenna के मूल अनुरोध का जवाब देने की जरूरत है और है कि एक धागा स्तर के लिए है कार्यान्वयन। विशेष रूप से डिवाइस फ़ंक्शन जिसे कर्नेल या थ्रेड के भीतर से बुलाया जा सकता है। क्षमा करें अगर मैंने "बोल्ड" वाक्यांशों को ओवरडिड किया है, लेकिन मुझे सच में लगता है कि अब तक के उत्तरों को काफी संबोधित नहीं किया जा रहा है।

कुंडल लाइब्रेरी आपकी सबसे अच्छी शर्त है। मैं सराहना करता हूं कि लोग पहिया को फिर से शुरू करना चाहते हैं (यह एक सराहना करता है और तीसरे पक्ष के पुस्तकालयों का अधिक उचित उपयोग करता है) लेकिन उच्च प्रदर्शन उच्च गुणवत्ता वाले नंबर जेनरेटर भरपूर और अच्छी तरह से परीक्षण किए जाते हैं। सबसे अच्छी जानकारी जो मैं अनुशंसा कर सकता हूं, यहां विभिन्न जेनरेटर पर जीएसएल लाइब्रेरी के लिए प्रलेखन पर है: http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

किसी भी गंभीर कोड के लिए गणितज्ञों/कंप्यूटर-वैज्ञानिकों के जमीन पर मुख्य एल्गोरिदम का उपयोग करना सबसे अच्छा है और प्रणालीगत कमजोरियों की तलाश में। "मेर्सन ट्विस्टर" 10^6000 (MT19997 एल्गोरिदम का अर्थ है "मेर्सन ट्विस्टर 2^1 999 7") के क्रम में एक अवधि (दोहराना लूप) के साथ कुछ है जिसे विशेष रूप से एनवीडिया के थ्रेड के भीतर थ्रेड स्तर पर उपयोग करने के लिए अनुकूलित किया गया है। बीज के रूप में थ्रेड आईडी कॉल का उपयोग कर एक ही वार। यहां पेपर देखें: http://developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf। मैं वास्तव में इस पुस्तकालय का उपयोग करके कुछ को लागू करने के लिए काम कर रहा हूं और अगर मैं इसे ठीक से काम करने के लिए प्राप्त करता हूं तो मैं अपना कोड पोस्ट करूंगा। वर्तमान CUDA टूलकिट के लिए एनवीडिया के पास उनकी प्रलेखन साइट पर कुछ उदाहरण हैं।

नोट: बस रिकॉर्ड के लिए मैं एनवीडिया के लिए काम नहीं करता हूं, लेकिन मैं अपने दस्तावेज और क्यूडीए के लिए अमूर्त डिज़ाइन स्वीकार करूंगा जो कुछ अब तक प्रभावित हुआ है।


0

आप Mersenne Twister for GPUs

यह SIMD उन्मुख फास्ट Mersenne ट्विस्टर (SFMT) जो एक काफी तेजी से और विश्वसनीय यादृच्छिक संख्या जनरेटर है पर आधारित है बाहर की कोशिश कर सकते। यह यादृच्छिक संख्या जनरेटर के लिए Marsaglias DIEHARD परीक्षण पास करता है।

+0

cuRAND पहले से ही [मेर्सन ट्विस्टर प्रदान करता है] (http://docs.nvidia.com/cuda/curand/acknowledgements.html#acknowledgements) GPU के लिए लागू किया गया है। –