使用线程安全随机数在c中进行多线程处理

时间:2014-12-05 00:38:15

标签: c multithreading

我一直试图通过valgrind泄漏检查,并传递20亿随机数并在线程之间划分它们。一旦我得到10亿个随机数,我就会遇到一个段错误。我在哪里分配错误或我做错了什么?

struct thread
{
    long long int threadID; //The thread id
    long long int operations; //The number of threads
};

void *generateThreads(void *ptr)
{
    struct thread *args = ptr;
    struct random_data *rdata = (struct random_data *) calloc(args->operations*64,sizeof(struct     random_data));
    char *statebuf = (char*) calloc(args->operations*64,BUFSIZE);
    long long int i;
    int32_t value;

    for(i = 0; i < args->operations; i++)
    {       
        initstate_r(args->threadID,&statebuf[i],BUFSIZE,&rdata[i]);
        random_r(rdata,&value);
    }

    if(DEBUG > 1)
        printf("I am thread %lld with thread id %X\n", args->threadID, (unsigned int) pthread_self());

    free(rdata);
    free(statebuf);
    pthread_exit(NULL);
}

int main(int argc, char **argv)
{
    long long int numRandoms;
    long long int numThreads;
    double timeStart = 0;
    double timeElapsed = 0;
    pthread_t *tid;
    struct thread args;

    if (argc != 3)
    {
         fprintf(stderr, "Usage: %s <Number of Randoms> <Number of Threads>\n" ,argv[0]);
         exit(1);
    }

   /* Assign the arg values to appropriate variables */
   sscanf(argv[1],"%lld",&numRandoms); /* lld for long long int */
   sscanf(argv[2],"%lld",&numThreads); /* lld for long long int */

   /* Number of threads must be less than or equal to the number of random numbers */
   if(numRandoms < numThreads)
   {
       fprintf(stderr,"Number of threads must be less than or equal to the number of random numers.\n");
       exit(1);
   }

   /*Start*/
   long long int i;
   args.operations = numRandoms/numThreads;
   timeStart = getMilliSeconds();
   tid = (pthread_t *) calloc(numThreads,sizeof(pthread_t));

   /* value is the thread id, creating threads */
   for(i = 0; i < numThreads; i++)
   {
       args.threadID = i;
       pthread_create(&tid[i],NULL,generateThreads,(void *) &args);
   }

   /* Joining the threads */
   for(i = 0; i < numThreads; i++)
   {
       pthread_join(tid[i],NULL);
   }

   /*Output*/
   timeElapsed = getMilliSeconds() - timeStart;
   printf("%lf\n",(double)(timeElapsed/1000.0));
   free(tid);
   fflush(stdout);
   exit(0);
}

2 个答案:

答案 0 :(得分:1)

好的,我弄清楚你要做什么。问题在于,您使用initstate_r中的main复制的代码来设置所有线程的状态。它为每个线程调用initstate_r一次以设置该线程的rng。但是你将这个循环复制到每个线程中,所以你每个线程多次调用initstate_r是没用的。 *64最初是为了使每个状态占用64个字节以使它们保持在单独的高速缓存行上。你可能指的是to this stackoverflow question

这是你的功能被重写以使其更有意义:

void *generateThreads(void *ptr)
{
    struct thread *args = ptr;
    struct random_data *rdata = calloc(1,sizeof(struct random_data));
    char statebuf[BUFSIZE];
    long long int i;
    int32_t value;

    initstate_r((int) pthread_self(),statebuf,BUFSIZE,rdata);
    for(i = 0; i < args->operations; i++)
    {
        random_r(rdata,&value);
        if(DEBUG > 1)
            printf("%d\n", value);
    }

    if(DEBUG > 1)
        printf("I am thread %lld with thread id %X\n", args->threadID, (unsigned int) pthread_self());

    free(rdata);
    pthread_exit(NULL);
}

顺便说一下,将参数传递给线程的方式是错误的。您将相同的args传递给每个线程,这意味着它们共享相同的args结构,这意味着它们各自共享相同的args->threadID。您应该将每个线程传递给它自己的args结构。

答案 1 :(得分:0)

我对问题link的回答提供了使用xorshift算法为__uint64 / __ uint128整数设计的线程安全伪随机数生成器。

其他属性:

  • 共享重入
  • 无锁
  • 线程安全
  • 超快
  • 来自两个不同来源的enthropy