请修改使用互斥量的Π计算程序,使临界区在for循环内。这个版本的性能与原来的忙等待版本相比如何?我们怎么解释它?
时间: 2023-07-14 11:14:28 浏览: 76
修改后的程序如下:
```c++
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 4
#define N 1000000000
double sum[NUM_THREADS] = {0.0};
double step = 1.0 / N;
pthread_mutex_t lock;
void *calc_pi(void *arg) {
long id = (long)arg;
int start = id * N / NUM_THREADS;
int end = (id + 1) * N / NUM_THREADS;
for (int i = start; i < end; i++) {
double x = (i + 0.5) * step;
double partial_sum = 4.0 / (1.0 + x*x);
pthread_mutex_lock(&lock);
sum[id] += partial_sum;
pthread_mutex_unlock(&lock);
}
pthread_exit(NULL);
}
int main() {
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&lock, NULL); // 初始化互斥量
for (long i = 0; i < NUM_THREADS; i++) {
pthread_create(&threads[i], NULL, calc_pi, (void*)i);
}
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
double pi = 0.0;
for (int i = 0; i < NUM_THREADS; i++) {
pi += sum[i] * step;
}
printf("pi = %.15lf\n", pi);
pthread_mutex_destroy(&lock); // 销毁互斥量
return 0;
}
```
在这个版本中,每个线程都会在循环内部执行临界区,即每个线程都会在循环内部对`sum`数组进行加法操作,而不是像之前的版本那样,每个线程都会在循环外部忙等待地对`sum`加锁、解锁和加法操作。
由于循环内部的临界区比循环外部的临界区更细粒度,所以这个版本的性能应该比原来的忙等待版本更好。这是因为:
- 每个线程只需要在本地修改`sum`数组的一个小部分,而不需要访问整个数组,从而减少了线程之间的竞争。
- 每个线程可以更频繁地访问`sum`数组,从而更充分地利用了缓存。
因此,这个版本的性能应该比原来的忙等待版本更好。
阅读全文