linux – 线程实现性能下降
我在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()和自己的缓冲区应该快得多. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |