#include<stdio.h> #include<unistd.h> #include<pthread.h> #include<stdlib.h> #include <time.h> #define random_1(a,b) ((rand()%(b-a))+a) //随机值将含a不含b pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int value = 0; long double valid=0,all=999999;//初始化有效点为0,总点数为999999 long double pi=0; void* fun(void* arg) { pthread_mutex_lock(&mutex); long double x,y;//定义坐标x,y int i=1; srand((double)time(NULL)); //设置随机数种子,防止每次产生的随机数相同 for(i=1;i<=999999;i++) { //获取x,y的随机值,0<=x<100000,0<=y<100000 x=random_1(0,100000); y=random_1(0,100000); if(x*x+y*y<=10000000000) valid++; } pthread_mutex_unlock(&mutex); return (void*)0; } //主函数 int main() { clock_t start, end; start = clock(); //读取程序开始运行的时间 pthread_t theradId1, threadId2;//定义两个子线程 int error;//定义线程返回值error,若是成功建立线程返回0,否则返回错误的编号 pthread_mutex_init(&mutex, NULL);//互斥锁初始化 error = pthread_create(&theradId1, NULL, fun, NULL); sleep(2);//用sleep()控制子线程的不同并发过程 if(error) { printf("Thread1 creat failed!\n"); exit(1); } error = pthread_create(&threadId2, NULL, fun, NULL); if(error) { printf("Thread2 creat failed!\n"); exit(1); } end = clock(); //记录结束时间 pi=valid/999999*4; printf("valid的值为: %Lf\n",valid); printf("总的点数的值为999999\n"); printf("π的值为: %Lf\n",pi); double seconds =(double)(end - start)/CLOCKS_PER_SEC*1000; printf("Use time is: %.3fms\n", seconds); //进程锁销毁 pthread_mutex_destroy(&mutex); return 0; } 对你编的程序,请回答以下问题:在你的机器上,创建多少个线程比较合适?为什么?需设计实验并获取实验数据,以验证你的答案。
时间: 2025-03-23 20:02:14 浏览: 37
### 程序分析及解答:
#### **问题概述**
该程序通过蒙特卡罗法计算圆周率 π 的近似值,并利用多线程技术提高性能。`fun()` 函数负责生成随机点并统计落入单位圆内的点数,主线程则汇总结果并输出最终的 π 值。
以下是关于“创建多少个线程比较合适”的详细回答以及相关的实验设计和数据分析思路。
---
### 创建线程的数量选择
1. **硬件资源限制**
- 当前计算机的核心数(CPU 核心数 + 超线程数)决定了可以同时运行的最大线程数。
- 如果创建过多线程,则操作系统会频繁地切换上下文(context switch),反而降低效率;而如果线程过少,无法充分利用 CPU 的并发能力。
2. **经验公式**
- 对于纯计算任务(如本程序中的随机数生成与条件判断),通常建议创建的线程数等于系统可用的核心数 `N_core` 或稍微超过一些(例如 2 * N_core)。这是因为部分核心可能会因等待 I/O 操作或其他原因闲置。
3. **实验目标**
- 测试不同线程数量对程序运行时间和准确性的综合影响。
- 找到既能缩短运行时间又能保证精度的最佳线程数目。
---
### 实验设计方案
#### (1)修改程序支持动态指定线程数
可以在程序中加入命令行参数或全局变量用于调整线程数量,例如:
```c
int num_threads = ...; // 用户输入或预设固定值
pthread_t threads[num_threads];
for(int i = 0; i < num_threads; ++i){
pthread_create(&threads[i], NULL, fun, NULL);
}
```
#### (2)测试范围设定
- 尝试从单线程开始逐渐增加至远超物理核心数量为止,比如 `[1, 8, 16, 32,...]`
- 记录每次试验所耗用的时间及时钟周期数据 (`clock()`) 和估算得到的 Pi 数值误差绝对量 |Pi_computed - Pi_actual|。
#### (3)收集指标包括但不限于以下几项:
- 平均每个线程处理的有效样本比例;
- 总体所需的实际运算秒数(ms);
- 得出的最后 Pi 接近度偏差程度(%).
---
### 数据采集示例表(假定)
| Thread Count | Execution Time (ms)| Estimated PI Value | Error (%) |
|--------------|--------------------|-------------------------|-----------|
| 1 | 5000 | 3.14| 0.07|
| 2 | 2700 | 3.14| 0.06|
| 4 | 1400 | 3.14| 0.05|
| 8 | 800 | 3.14| 0.04|
| 16 | 1000 | 3.14| 0.05|
注释: 随着线程数量增多,在达到某个临界点之前(这里假设为8), 时间减少明显,之后由于竞争加剧导致整体延迟变长.
---
### 结论推断
基于上述模拟表格可以看出:
- 最优解可能出现在接近实际处理器逻辑单元数量的位置附近.
- 过度分配额外工作给更多线程并未带来显著收益甚至适得其反.
因此结论应结合自身设备配置得出确切数字推荐!
---
阅读全文
相关推荐



















