سؤال

لقد كافحت مع هذا طوال اليوم، وأنا أحاول الحصول على منشئ أرقام عشوائية للسلاسل في كود CUDA الخاص بي.لقد بحثت في جميع المنتديات ونعم هذا الموضوع يظهر إلى حد ما ولكني أمضيت ساعات في محاولة كشف جميع أنواع الرموز دون جدوى.إذا كان أي شخص يعرف طريقة بسيطة، فمن المحتمل أن يكون أ جهاز kernel الذي يمكن استدعاؤه لإرجاع تعويم عشوائي بين 0 و 1، أو عددًا صحيحًا يمكنني تحويله سأكون في غاية الامتنان.

مرة أخرى، أتمنى استخدام الرقم العشوائي الموجود في النواة، تمامًا مثل rand() على سبيل المثال.

شكرا لك مقدما

هل كانت مفيدة؟

المحلول

لست متأكدًا من أنني أفهم سبب حاجتك إلى أي شيء خاص.يجب أن يتم تنفيذ أي PRNG تقليدي بشكل مباشر تقريبًا.أ متطابقة خطية يجب أن تعمل بشكل جيد.هل لديك بعض العقارات المميزة التي تحاول تأسيسها؟

نصائح أخرى

لأي شخص مهتم، يمكنك الآن القيام بذلك عبر cuRAND.

أعتقد أن أي مناقشة لهذا السؤال تحتاج إلى إجابة لطلب Zenna الأصلي، وذلك من أجل أ مستوى الخيط تطبيق.على وجه التحديد أ وظيفة الجهاز التي يمكن استدعاؤها من داخل النواة أو الخيط.آسف إذا بالغت في استخدام العبارات "بالخط العريض" ولكني أعتقد حقًا أن الإجابات حتى الآن لا تعالج تمامًا ما هو مطلوب هنا.

مكتبة cuRAND هي أفضل رهان لك.أقدر رغبة الناس في إعادة اختراع العجلة (فهذا يجعل المرء يقدر مكتبات الطرف الثالث ويستخدمها بشكل أكثر ملاءمة) ولكن مولدات الأرقام عالية الجودة عالية الأداء متوفرة بكثرة وتم اختبارها جيدًا.أفضل المعلومات التي يمكنني التوصية بها هي في وثائق مكتبة GSL على المولدات المختلفة هنا:http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

بالنسبة لأي كود جدي، من الأفضل استخدام إحدى الخوارزميات الرئيسية التي يستخدمها علماء الرياضيات/علماء الكمبيوتر مرارًا وتكرارًا بحثًا عن نقاط الضعف النظامية."Mersenne Twister" هو شيء ذو فترة (حلقة متكررة) في حدود 10^6000 (خوارزمية MT19997 تعني "Mersenne Twister 2^19997") والذي تم تكييفه خصيصًا لـ Nvidia لاستخدامه على مستوى الخيط داخل سلاسل الرسائل. نفس الالتواء باستخدام مكالمات معرف الخيط كبذور.انظر الورقة هنا:http://developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf.أنا أعمل بالفعل على تنفيذ شيء ما باستخدام هذه المكتبة، وإذا جعلتها تعمل بشكل صحيح، فسوف أقوم بنشر الكود الخاص بي.لدى Nvidia بعض الأمثلة في موقع التوثيق الخاص بها لمجموعة أدوات CUDA الحالية.

ملحوظة:للعلم فقط، أنا لا أعمل لدى Nvidia، لكنني سأعترف بأن تصميم التوثيق والتجريد الخاص بهم لـ CUDA هو شيء أعجبت به حتى الآن.


اعتمادًا على التطبيق الخاص بك، يجب أن تكون حذرًا عند استخدام الواقيات الأساسية لإنقاذ الحياة دون النظر فيما إذا كانت التدفقات (تيار واحد لكل خيط) ستتداخل.يمكنك تنفيذ قفزة باستخدام الواقيات الأساسية لإنقاذ الحياة، ولكن بعد ذلك ستحتاج إلى الحصول على الواقي الأساسي لإنقاذ الحياة لفترة طويلة بما فيه الكفاية لضمان عدم تكرار التسلسل.

مثال على القفزة يمكن أن يكون:

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);

    ...
}

ولكن من المحتمل أن تكون فترة هذا المولد غير كافية في معظم الحالات.

لأكون صادقًا، سأفكر في استخدام مكتبة تابعة لجهة خارجية مثل تذمر.هناك بعض المولدات المجمعة في SDK أيضًا، ولكن ربما لا يكون هذا ما تبحث عنه في هذه الحالة.

يحرر

نظرًا لأنه تم التصويت على هذا للتو، أعتقد أنه من المفيد التحديث لذكر ذلك cuRAND, ، كما ذكرنا في أحدث الإجابات على هذا السؤال، متاح ويوفر عددًا من المولدات والتوزيعات.هذا بالتأكيد هو أسهل مكان للبدء.

أفضل طريقة لذلك هي الكتابة بنفسك جهاز وظيفة، هنا هو واحد

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 */
    }
}

سيعطيك 100 رقم عشوائي بنتيجة 32 بت.

إذا كنت تريد بعض الأرقام العشوائية بين 1 و1000، فيمكنك أيضًا أخذها result%1000, إما عند نقطة الاستهلاك أو عند نقطة التوليد:

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

يتيح لك تغيير قيم البدء m_w وm_z (في المثال 150 و40) الحصول على نتائج مختلفة في كل مرة.يمكنك استخدام threadIdx.x كواحد منهم، والذي يجب أن يمنحك سلسلة عشوائية زائفة مختلفة في كل مرة.

أردت أن أضيف أنها تعمل أسرع مرتين من وظيفة rand()، وتعمل بشكل رائع؛)

توجد حزمة MDGPU (GPL) تتضمن تنفيذ وظيفة GNU rand48() لـ CUDA هنا.

لقد وجدته (بسهولة تامة، باستخدام Google، والذي أفترض أنك حاولت :-) في منتديات NVidia هنا.

لم أجد مولد أرقام متوازية جيدًا لـ CUDA، ومع ذلك فقد وجدت مولد أرقام عشوائية متوازية استنادًا إلى البحث الأكاديمي هنا: http://sprng.cs.fsu.edu/

هل يمكن أن تجرب Mersenne Twister لوحدات معالجة الرسومات

وهو يعتمد على Fast Mersenne Twister (SFMT) الموجه نحو SIMD وهو مولد أرقام عشوائي سريع وموثوق به.اجتاز اختبارات Marsaglias DIEHARD لمولدات الأرقام العشوائية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top