多线程蒙特卡洛法计算PI的C语言代码非void返回报错问题求解
问题修复方案
编译报错的根因
你遇到的non-void function doesn't return a value报错,是因为runner作为pthread线程入口函数,声明的返回类型是void*,但函数末尾没有返回任何值,不符合C语言的语法要求。
额外问题说明
你的原有代码还存在两处逻辑错误:
- 计算PI的分母使用了初始值为0的局部变量
points_per_thread,会触发除0错误,得到无效的无穷大结果 - 没有实现你要求的「每结束一个线程就更新一次PI值」的逻辑,原有代码是所有线程执行完毕后才计算一次PI值
完整修正代码
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <time.h> long ppt; /* 每个线程生成的点数量 */ void *runner() { long incircle_thread = 0; unsigned int rand_state = rand(); for (long i = 0; i < ppt; i++) { double x = rand_r(&rand_state) / ((double)RAND_MAX + 1) * 2.0 - 1.0; double y = rand_r(&rand_state) / ((double)RAND_MAX + 1) * 2.0 - 1.0; if (x * x + y * y < 1) { incircle_thread++; } } // 返回当前线程统计的圆内点数,无需全局锁 return (void*)incircle_thread; } int main(int argc, const char *argv[]) { if (argc != 3) { fprintf(stderr, "usage: ./pi <总生成点数> <线程数>\n"); exit(1); } long totalpoints = atol(argv[1]); int thread_count = atoi(argv[2]); ppt = totalpoints / thread_count; time_t start = time(NULL); srand((unsigned)time(NULL)); pthread_t *threads = malloc(thread_count * sizeof(pthread_t)); pthread_attr_t attr; pthread_attr_init(&attr); for (int i = 0; i < thread_count; i++) { pthread_create(&threads[i], &attr, runner, NULL); } long total_incircle = 0; for (int i = 0; i < thread_count; i++) { void *ret; pthread_join(threads[i], &ret); // 累加当前线程返回的圆内点数 total_incircle += (long)ret; // 每结束一个线程就更新计算PI值 double current_pi = 4.0 * total_incircle / (double)(ppt * (i + 1)); printf("第%d个线程执行完毕,当前PI计算值:%f\n", i+1, current_pi); } free(threads); printf("\n最终PI计算值:%f\n", 4.0 * (double)total_incircle / (double)totalpoints); printf("总耗时:%d 秒\n", (unsigned int)(time(NULL) - start)); return 0; }
使用说明
如果要实现你要求的「5个线程每个生成1000个点」的效果,编译后执行以下命令即可:
./pi 5000 5
内容的提问来源于stack exchange,提问作者Bam19
相关产品推荐
相关产品推荐

