并行化阶乘计算
Parallelizing Factorial Calculation
我想编写一个程序来计算整数的阶乘,使用并行计算(Open MP 库)。
很明显下面的程序存在竞争条件。
// Each loop iteration writes a value that a different iteration reads.
#pragma omp parallel for
for (i=2; i < 10; i++)
{
factorial[i] = i * factorial[i-1];
}
我在某处读到 pow 和阶乘计算绝不能并行完成。那么,这是真的吗,还是可以修改上述程序(在 C 中,使用 OPenMP 库)以并行计算阶乘?
如果它是一个大数,你可以拆分你的乘法来做一个平行阶乘
例子
人数是1000人!你有 10 个线程
- 线程解析2*3*4*5*.....*100并保存在t1
线程解析101*102*103 .... *200并保存在t2
.....
10) 线程解析 900*901*902*....*1000 并保存在 t10
然后在主线程上解决:
t1*t2*t3*...*t10 等于 1000!
您可以通过 运行 在数组上并行执行此操作两次。第一次计算部分产品并保存每个线程的部分产品总数。在第二遍中,您根据前一个线程的总积更正每个元素。这类似于如何并行计算累积和(又名前缀和),只是它是并行累积乘积。
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(void) {
int n = 10;
int factorial[n];
factorial[1] = 1;
int *proda;
#pragma omp parallel
{
int ithread = omp_get_thread_num();
int nthreads = omp_get_num_threads();
#pragma omp single
{
proda = malloc(nthreads * sizeof *proda);
proda[0] = 1;
}
int prod = 1;
#pragma omp for schedule(static) nowait
for (int i=2; i<n; i++) {
prod *= i;
factorial[i] = prod;
}
proda[ithread+1] = prod;
#pragma omp barrier
int offset = 1;
for(int i=0; i<(ithread+1); i++) offset *= proda[i];
#pragma omp for schedule(static)
for(int i=1; i<n; i++) factorial[i] *= offset;
}
free(proda);
for(int i=1; i<n; i++) printf("%d\n", factorial[i]); putchar('\n');
}
我想编写一个程序来计算整数的阶乘,使用并行计算(Open MP 库)。
很明显下面的程序存在竞争条件。
// Each loop iteration writes a value that a different iteration reads.
#pragma omp parallel for
for (i=2; i < 10; i++)
{
factorial[i] = i * factorial[i-1];
}
我在某处读到 pow 和阶乘计算绝不能并行完成。那么,这是真的吗,还是可以修改上述程序(在 C 中,使用 OPenMP 库)以并行计算阶乘?
如果它是一个大数,你可以拆分你的乘法来做一个平行阶乘
例子
人数是1000人!你有 10 个线程
- 线程解析2*3*4*5*.....*100并保存在t1
线程解析101*102*103 .... *200并保存在t2
.....
10) 线程解析 900*901*902*....*1000 并保存在 t10
然后在主线程上解决:
t1*t2*t3*...*t10 等于 1000!
您可以通过 运行 在数组上并行执行此操作两次。第一次计算部分产品并保存每个线程的部分产品总数。在第二遍中,您根据前一个线程的总积更正每个元素。这类似于如何并行计算累积和(又名前缀和),只是它是并行累积乘积。
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(void) {
int n = 10;
int factorial[n];
factorial[1] = 1;
int *proda;
#pragma omp parallel
{
int ithread = omp_get_thread_num();
int nthreads = omp_get_num_threads();
#pragma omp single
{
proda = malloc(nthreads * sizeof *proda);
proda[0] = 1;
}
int prod = 1;
#pragma omp for schedule(static) nowait
for (int i=2; i<n; i++) {
prod *= i;
factorial[i] = prod;
}
proda[ithread+1] = prod;
#pragma omp barrier
int offset = 1;
for(int i=0; i<(ithread+1); i++) offset *= proda[i];
#pragma omp for schedule(static)
for(int i=1; i<n; i++) factorial[i] *= offset;
}
free(proda);
for(int i=1; i<n; i++) printf("%d\n", factorial[i]); putchar('\n');
}