微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在线程中计算Pi

我有两个使用 Monte-Carlo method计算pi的实现:有线和无线程.没有线程工作的实现很好,但带线程的方法在准确性和性能方面存在问题.这是代码

没有线程:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main()
{
    srand(time(NULL));

    unsigned long N = 0,Nin = 0;
    float x,y;

    while(N < 2E+9)
    {
        x = rand()/((float)RAND_MAX + 1.0)*10.0 - 5.0;
        y = rand()/((float)RAND_MAX + 1.0)*10.0 - 5.0;

        if(x*x + y*y < 25.0) Nin += 1;
        N++;
    }
    long double pi = 4.0 * (long double)Nin / (long double)N;

    printf("\tPi1: %.20Lf\n\t%lu %lu\n",pi,Nin,N);

    return 0;
}

并有线程:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>


typedef struct 
{
    unsigned long Nin;
    unsigned long N;
} nums;


void pi_counter(nums* a)
{
    float x,y;
    unsigned int N = 0,Nin = 0;

    while(N < 1E+9)
    {
        x = rand()/((float)RAND_MAX + 1.0)*10.0 - 5.0;
        y = rand()/((float)RAND_MAX + 1.0)*10.0 - 5.0;


        if(x*x + y*y < 25.0) Nin++;
        N++;
    }

    a -> Nin += Nin;
    a -> N   += N;
}


int main()
{
    pthread_t thread1,thread2,thread3;
    nums a;

    srand(time(NULL));

    pthread_create( &thread1,NULL,pi_counter,&a );
    pthread_create( &thread2,&a );

    pthread_join( thread1,NULL );
    pthread_join( thread2,NULL ); 

    long double pi = 4.0 * (long double)a.Nin / (long double)a.N;


    printf("\tPi2: %.20Lf\n\t%lu %lu\n",a.Nin,a.N);

    return 0;
}

结果:

$time ./pi2
    Pi2: 3.14147154999999999995
    1570735775 2000000000

real    1m1.927s
user    1m23.624s
sys 0m0.139s



$time ./pi
    Pi1: 3.14158868600000000006
    1570794343 2000000000

real    0m49.956s
user    0m49.887s
sys 0m0.022s

我的错误在哪里?

解决方法

兰德不是线程安全的;在多个线程中同时使用它将导致未定义的行为.您可以使用在调用rand时获取并保存互斥锁的函数来包装它,或者您可以使用rand_r或(更好)编写一个体面的PRNG来代替它使用.

原文地址:https://www.jb51.cc/c/116897.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐