我试图用递归的并发程序计算pi。程序以不同的精确度计算pi。
我有一个有效的代码和一个没有代码的代码。两者之间唯一不同的部分是在创建线程时如何传递参数。两个版本都创建 np 线程并将它们传递给递归函数。他们传递的论点是结构:
struct args{double l, r, fl, fr, area; long id;};
并将它传递给函数parallel_quad:
void *parallel_quad(void *myargs) {
struct args *args = myargs;
/* passing the arguments to local variables */
double l = args->l;
double r = args->r;
double fl = args->fl;
double fr = args->fr;
double area = args->area;
/* calculating the new parameters using the
adaptive quadrature routine formulas */
double m = (l+r)/2;
double fm = f(m);
double larea = (fl+fm)*(m-l)/2;
double rarea = (fm+fr)*(r-m)/2;
/* if the result is not within the given error estimate,
continue the recursion */
if (fabs((larea + rarea) - area) > epsilon) {
args->l = l;
args->r = m;
args->fl = fl;
args->fr = fm;
args->area = larea;
parallel_quad(args);
args->l = m;
args->r = r;
args->fl = fm;
args->fr = fr;
args->area = rarea;
parallel_quad(args);
} else {
result[args->id] += larea + rarea;
}
}
有效的(它返回pi = 3.14159265354728356456)使用数组作为参数。看起来像这样
struct args args[np];
for (i = 0; i < np; i++){
args[i].id = i;
args[i].l = i * dxPerThread;
args[i].r = args[i].l + dxPerThread;
args[i].fl = f(args[i].l);
args[i].fr = f(args[i].r);
args[i].area = (f(args[i].l)+f(args[i].r))*(args[i].r-args[i].l)/2;
pthread_create(&workerid[i], NULL, parallel_quad, &args[i]);
}
虽然不起作用的版本(它返回pi = 3.26262338311626587384)看起来像这样
for (i = 0; i < np; i++){
id = i;
l = i * dxPerThread;
r = l + dxPerThread;
fl = f(l);
fr = f(r);
area = (f(l)+f(r))*(r-l)/2;
struct args *myargs = malloc(sizeof(struct args));
myargs->l = l;
myargs->r = r;
myargs->fl = fl;
myargs->fr = fr;
myargs->area = area;
myargs->id = id;
pthread_create(&workerid[i], NULL, parallel_quad, (void*)myargs);
}
和另一个版本,返回pi = 0.12103072956898178192,看起来像这样
for (i = 0; i < np; i++){
id = i;
l = i * dxPerThread;
r = l + dxPerThread;
fl = f(l);
fr = f(r);
area = (f(l)+f(r))*(r-l)/2;
struct args *myargs = malloc(sizeof(struct args));
myargs->l = l;
myargs->r = r;
myargs->fl = fl;
myargs->fr = fr;
myargs->area = area;
myargs->id = id;
pthread_create(&workerid[i], NULL, parallel_quad, &myargs);
}
并且,碰巧,3.26262338311626587384 - 0.12103072956898178192 = 3.14159265354728356456。我对C,指针和结构都很陌生,我真的不明白这里发生了什么。似乎有效的版本传递一个指向结构的地址的指针,该结构包含参数(struct args *),而另一个传递一个void-pointer(void *)。换句话说,有效的那个通过堆栈上的地址,而不起作用的地址传递指向堆的指针。有什么区别?为什么两者都没有返回相同的值?