2011-10-17 19 views
7

साथ सी में यादृच्छिक संख्या उत्पन्न करने के लिए है मैं समवर्ती चलती कई सूत्र है और उनमें से प्रत्येक यादृच्छिक संख्या उत्पन्न करनी चाहिये। मैं अगर वहाँ एक पैटर्न का पालन करने के लिए है समझने के लिए, समझने के लिए चाहते हैं, तो इसके साथ srand मुख्य थ्रेड में या अगर हर धागा अपने स्वयं के यादृच्छिक जनरेटर को प्रारंभ करना चाहिए यादृच्छिक जनरेटर प्रारंभ करने में सही है। ऐसा लगता है कि रैंड/srand को थ्रेड के साथ उपयोग करने के लिए डिज़ाइन नहीं किया गया है और मैं सोच रहा हूं कि मैं धागे और यादृच्छिक संख्याओं के साथ कैसे निपट सकता हूं। धन्यवादक्या सबसे सही तरीका pthread

संपादित करें: मुझे शुद्ध यादृच्छिक संख्या की आवश्यकता है, लेकिन मैं परीक्षण उद्देश्यों के लिए एक निर्धारिक अनुक्रम उत्पन्न करने में भी रूचि रखता हूं। मैं लिनक्स पर हूं, लेकिन मैं जितना संभव हो पोर्टेबल कोड लिखना पसंद करता हूं।

+2

के आधार पर उपयोग करने के बजाय आप अनुक्रम या नियतात्मक नहीं करना चाहते हैं? - http://stackoverflow.com/questions/6467585/deterministic-random-number-generator-tied-to-instance-thread-independent/6467623#6467623 – Flexo

+1

आप कोई विशेष आवश्यकता है, तो 'rand_r' का उपयोग करें। –

+1

रैंड() लिनक्स पर थ्रेड सुरक्षित है लेकिन पॉज़िक्स द्वारा ऐसा करने की आवश्यकता नहीं है, हालांकि posix उस उद्देश्य के लिए rand_r प्रदान करता है। glibc अपने रैंड() के लिए एक आंतरिक म्युटेक्स उपयोग करता है - विवाद के कारण हो सकता है जो अगर आपके सूत्र उत्पन्न यादृच्छिक संख्या का एक बहुत – nos

उत्तर

7

लिनक्स पर आप एक औसत जनरेटर के लिए rand_r() या drand48_r() फ़ंक्शन को बेहतर तरीके से उपयोग कर सकते हैं। दोनों rand() और drand48() के लिए धागा सुरक्षित प्रतिस्थापन, एक भी वर्तमान स्थिति से मिलकर तर्क लेने के बजाय वैश्विक राज्य का उपयोग करके कर रहे हैं।

प्रारंभ में आपके प्रश्न के संबंध में

, जेनरेटर के दोनों ऊपर आप जो कुछ भी बात आप की इच्छा पर बीज के ताकि आप अपने धागे को उत्पन्न करने से पहले उन्हें बीज के लिए मजबूर नहीं कर रहे हैं अनुमति देते हैं।

+1

rand_r अप्रचलित है POSIX 2008 के बाद से मैं पता नहीं क्यों, लेकिन अच्छा लगेगा। –

0

विंडोज पर आप rand_s() समारोह है, जो सुरक्षित थ्रेड है उपयोग कर सकते हैं। आप पहले से ही बूस्ट का उपयोग कर रहे हैं, तो boost::random (हालांकि मुझे खुशी इस टैग है सी, सी ++ नहीं) सक्षम है।

0

यह लिंक/dev/यादृच्छिक से पढ़ने के लिए कुछ कोड प्रदान करता है - जो धागे की सुरक्षित होना चाहिए - और सवाल उसी तर्ज पर है:

Is reading /dev/urandom thread-safe?

4

जब धागे के साथ काम करने और कर उदाहरण के लिए सिमुलेशन या इसलिए यह बहुत महत्वपूर्ण है कि आपके पास यादृच्छिक जेनरेटर स्वतंत्र हैं। सबसे पहले, उनके बीच निर्भरता वास्तव में आपके परिणामों को पूर्वाग्रह कर सकती है और फिर यादृच्छिक जनरेटर की स्थिति तक पहुंच नियंत्रण के लिए तंत्र संभवतः निष्पादन धीमा कर देगा।

POSIX सिस्टम पर (आप होने लगते हैं जहां) है कार्यों जहां erand48, nrand48 और jrand48 इनपुट मानों के रूप में यादृच्छिक जनरेटर के राज्य लेने के *rand48 परिवार। तो आप प्रत्येक धागे में आसानी से स्वतंत्र राज्य कर सकते हैं। जिन्हें आप किसी ज्ञात संख्या (जैसे आपके धागे की संख्या) के साथ प्रारंभ कर सकते हैं और आपके पास यादृच्छिक संख्याओं का पुनरुत्पादन अनुक्रम होगा। या आप इसे गैर-अनुमानित कुछ के साथ प्रारंभ करते हैं जैसे वर्तमान समय & प्रत्येक निष्पादन के लिए अलग-अलग अनुक्रमों की संख्या।

1

rand_r थ्रेड-सुरक्षित है लेकिन पुनर्विक्रेता भी है।

नीचे कोड xorshift एल्गोरिदम का उपयोग करते हुए uint128_t छद्म-यादृच्छिक संख्या उत्पन्न करता है।

अतिरिक्त गुण:

  • साझा-रैत्रांत
  • ताला मुक्त
  • धागा सुरक्षित
  • ultrafast
  • enthropy

uintx_types के दो संस्करण स्रोतों से वरीयता प्राप्त।ज:

#ifndef UINTX_TYPES_H_INCLUDED 
#define UINTX_TYPES_H_INCLUDED 

#include <inttypes.h> 
#include <ctype.h> 

typedef __uint128_t  uint128_t; 
typedef __uint64_t  uint64_t; 

#define UINT128_C(hi, lo) (((uint128_t)(hi) << 64) | (uint128_t)(lo)) 
#define UINT128_MIN   UINT128_C(0x0000000000000000, 0x0000000000000000) 
#define UINT128_0   UINT128_MIN 
#define UINT128_MAX   (~(UINT128_0) - 1) 

#endif // UINTX_TYPES_H_INCLUDED 

lf.h:

#ifndef LF_H_INCLUDED 
#define LF_H_INCLUDED 

#define AAF(ADDR, VAL)   __sync_add_and_fetch((ADDR), (VAL)) 

#endif // LF_H_INCLUDED 

rand.h:

#ifndef RAND_H_INCLUDED 
#define RAND_H_INCLUDED 

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <time.h> 
#include <limits.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <unistd.h> 

#include "lf.h" 
#include "uintx_types.h" 


#define URANDOM  "/dev/random" 

void  srand_init(void); 
uint128_t rand_range_128(uint128_t min, uint128_t max); 

#endif // RAND_H_INCLUDED 

rand.c:

#include "rand.h" 

uint64_t r[2]; 

uint64_t xorshift64star(int index) 
{ 
    uint64_t x; 

    x = r[index]; 
    x ^= x >> 12; // a 
    x ^= x << 25; // b 
    x ^= x >> 27; // c 
    x = x * UINT64_C(2685821657736338717); 
    return AAF(&r[index], x); 
} 

void srand_init(void) 
{ 
    struct timespec ts; 
    size_t   nbytes; 
    ssize_t   bytes_read; 
    int    fd; 

    clock_gettime(CLOCK_REALTIME, &ts); 
    r[0] = (uint64_t)(ts.tv_sec * 1.0e9 + ts.tv_nsec); 
    xorshift64star(0); 

    if ((fd = open(URANDOM, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH)) == -1) 
    { 
     r[1] = r[0] + 1; 
     xorshift64star(1); 
    } 
    else 
    { 
     nbytes = sizeof(r[1]); 
     bytes_read = read(fd, &r[1], nbytes); 
     if ((bytes_read == 0) || (r[1] == 0ull)) 
     { 
      r[1] = r[0] + 1; 
      xorshift64star(1); 
     } 
     close(fd); 
    } 
} 

uint64_t rand_64(void) 
{ 
    return xorshift64star(0); 
} 

uint128_t rand_128(void) 
{ 
    uint128_t  r; 

    r = xorshift64star(0); 
    r = (r << 64) | xorshift64star(1); 
    return r; 
} 


uint128_t rand_range_128(uint128_t min, uint128_t max) 
{ 
    return (rand_128() % (max+1-min))+min; 
} 

test.c:

#define KEYS 1000 

int main(int argc, char **argv) 
{ 
    int    i; 
    uint128_t  key; 

    srand_init(); 

    for(i = 0; i <= KEYS; i++) 
    { 
     key = rand_range_128(UINT128_MIN, UINT128_MAX); 
     printf("%016"PRIx64"%016"PRIx64"\n", (uint64_t)(key >> 64), (uint64_t)key); 

    } 
    return 0; 
} 
जीसीसी (4.9.2) लिनक्स के तहत साथ

संकलित करें।

+0

यहां "नेक्रोप्रोस्टिंग" के लिए खेद है, लेकिन मैं यह पूछना चाहता था कि क्या मैं srand_init (unsigned int * seed) में srand_init (शून्य) को संशोधित कर सकता हूं और घड़ी_gettime (CLOCK_REALTIME, &ts); r [0] = (uint64_t) (ts) .tv_sec * 1.0e9 + ts.tv_nsec);। सीधे शब्दों में आर [0] = uint64_t (* बीज), तो मैं हमेशा अपने RNG प्रारंभ करने में कैसे इसके अलावा चयन कर सकते हैं –

+0

, मैं एक threadsafe तरीके से इस RNG कैसे प्रारंभ करना चाहिए? मैं अपने धागे को उगता हूं और फिर बीज को बदलता हूं और हर धागे में srand_init (बीज) का उपयोग करता हूं? या मैं अपने समांतर क्षेत्र के अंदर सुरक्षित रूप से rand_range_128 (UINT128_MIN, UINT128_MAX) को कॉल कर सकता हूं? –

0

तरह Linux सिस्टम पर आप एक समारोह का उपयोग कर सकते हैं:

size_t random_between_range(size_t min, size_t max){ 
    unsigned short state[3]; 
    unsigned int seed = time(NULL) + (unsigned int) pthread_self(); 
    memcpy(state, &seed, sizeof(seed)); 
    return min + nrand48(state) % (max - min); 
} 

यहाँ मैं कहना है कि मैं वास्तव में नहीं है पता है कि इस समारोह है अगर अगर दूसरे शब्दों में सामान्य वितरण करने के लिए इस समारोह फिट द्वारा उत्पन्न नंबर हैं सीमा में एक वैध आरएनजी (न्यूनतम, अधिकतम) लेकिन कम से कम मेरे लिए एक साधारण बेंचमार्क लिखने के लिए काम किया जिसके लिए कुछ यादृच्छिक संख्याएं आवश्यक थीं।

आप देख सकते हैं, समारोह क्रम में यादृच्छिक बीज फिर से व्यवस्थित में POSIX धागा आईडी का इस्तेमाल करता है। ऐसा करने से, प्रत्येक थ्रेड यह यादृच्छिक बीज ही है वैश्विक राज्य time(NULL)

संबंधित मुद्दे