加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – 线程实现性能下降

发布时间:2020-12-14 00:05:07 所属栏目:Linux 来源:网络整理
导读:我在C中实施了一个小程序,使用蒙特卡罗方法计算PI(主要是因为个人兴趣和培训).在实现了基本代码结构之后,我添加了一个命令行选项,允许执行线程计算. 我预计会有很大的加速,但我很失望.命令行概要应该是清楚的.用于近似PI的最终迭代次数是通过命令行传递的-it
我在C中实施了一个小程序,使用蒙特卡罗方法计算PI(主要是因为个人兴趣和培训).在实现了基本代码结构之后,我添加了一个命令行选项,允许执行线程计算.

我预计会有很大的加速,但我很失望.命令行概要应该是清楚的.用于近似PI的最终迭代次数是通过命令行传递的-iterations和-threads的乘积. Leaving -threads blank将其默认为1个线程,导致在主线程中执行.

下面的测试总共进行了80万次迭代测试.

在Windows 7 64Bit(Intel Core2Duo Machine)上:

使用Cygwin GCC 4.5.3编译:gcc-4 pi.c -o pi.exe -O3

在Ubuntu / Linaro 12.04(8核心AMD):

使用GCC 4.6.3编译:gcc pi.c -lm -lpthread -O3 -o pi

性能

在Windows上,线程版本比非线程版本快几毫秒.说实话,我期待更好的表现.在Linux上,哇!有没有搞错?为什么它甚至需要2000%的时间?当然,这在很大程度上取决于实现,所以在这里.完成命令行参数解析后的摘录并开始计算:

// Begin computation.
    clock_t t_start,t_delta;
    double pi = 0;

    if (args.threads == 1) {
        t_start = clock();
        pi = pi_mc(args.iterations);
        t_delta = clock() - t_start;
    }
    else {
        pthread_t* threads = malloc(sizeof(pthread_t) * args.threads);
        if (!threads) {
            return alloc_failed();
        }

        struct PIThreadData* values = malloc(sizeof(struct PIThreadData) * args.threads);
        if (!values) {
            free(threads);
            return alloc_failed();
        }

        t_start = clock();
        for (i=0; i < args.threads; i++) {
            values[i].iterations = args.iterations;
            values[i].out = 0.0;
            pthread_create(threads + i,NULL,pi_mc_threaded,values + i);
        }
        for (i=0; i < args.threads; i++) {
            pthread_join(threads[i],NULL);
            pi += values[i].out;
        }
        t_delta = clock() - t_start;

        free(threads);
        threads = NULL;
        free(values);
        values = NULL;

        pi /= (double) args.threads;
    }

而pi_mc_threaded()实现为:

struct PIThreadData {
    int iterations;
    double out;
};

void* pi_mc_threaded(void* ptr) {
    struct PIThreadData* data = ptr;
    data->out = pi_mc(data->iterations);
}

您可以在http://pastebin.com/jptBTgwr找到完整的源代码.

为什么是这样?为什么Linux上存在这种极端差异?我预计计算的时间至少是原始时间的3/4.当然有可能我只是错误地使用了pthread库.在这种情况下如何做正确的澄清将是非常好的.

解决方法

问题是在glibc的实现中,rand()调用 __random(),那就是

long int
__random ()
{
  int32_t retval;

  __libc_lock_lock (lock);

  (void) __random_r (&unsafe_state,&retval);

  __libc_lock_unlock (lock);

  return retval;
}

锁定每次调用函数__random_r来执行实际工作.

因此,只要您使用rand()有多个线程,就会使每个线程在几乎每次调用rand()时都等待其他线程.在每个线程中直接使用random_r()和自己的缓冲区应该快得多.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读