代码之家  ›  专栏  ›  技术社区  ›  ferrer

并行化因子计算

  •  6
  • ferrer  · 技术社区  · 10 年前

    我想编写一个程序,使用并行计算(OpenMP库)计算整数的阶乘。

    显然,下面的程序存在种族问题。

    // 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];
    }
    

    我在某处读到,幂和阶乘计算决不能并行进行。那么,这是真的吗,还是可以修改上述程序(在C中,使用OPenMP库)以并行计算阶乘?

    2 回复  |  直到 6 年前
        1
  •  4
  •   Z boson    10 年前

    您可以通过在阵列上运行两次来并行执行此操作。第一次计算部分产品并保存每个线程的总部分产品时。在第二遍中,您用前一个线程的总乘积来校正每个元素。这类似于如何并行进行累积和(又名前缀和),只是它是并行的累积积。

    #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'); 
    }
    
        2
  •  4
  •   ganchito55    10 年前

    如果它是一个大数字,如果您拆分乘法,您可以进行并行阶乘

    实例

    数字是1000!你有10根线

    1. 线程解析2*3*4*5*…..*100并保存在t1中
    2. 线程解析101*102*103….*200并保存在t2中

      ....

    10) 线程解析900*901*902*….*1000并保存到t10

    然后在主线程上解析:

    t1*t2*t3*…*t10,它等于1000!