【问题标题】:Distribution of loop iterations between threads with a specific order具有特定顺序的线程之间的循环迭代分布
【发布时间】:2021-12-27 17:48:27
【问题描述】:

我有这个系列代码:

for (i=0; i<N; i++) 
{
    printf ("\n% i = d\n", i);
    C[i] = 0;
    for (j=0; j<N; j++) C[i] += MAT[i][j] * B[j];
    x += C[i];
}

我想制作一个简单的并行版本,只有一个 pragma 并行,但困难的想法是分配迭代执行顺序的规范,例如:

 i = 0 
 i = n
 i = 1
 i = n-1
 //The rest of iterations

如果我知道使用的线程数,我可以制作一个并行版本,但它必须使用任何偶数线程打印该订单我知道我必须使用 omp_get_num_threads 来跟踪它,但我无法做到,谢谢

【问题讨论】:

    标签: c algorithm for-loop parallel-processing openmp


    【解决方案1】:

    我看到的问题是,如果您想像这样分配迭代: 0123...3210(编号为线程,位置为迭代) 您必须修改循环,因为我看到如果您不跟踪 N-i-1 迭代,您将无法做到这一点,因此代码将如下所示:

    #pragma omp parallel for private (i, j, k) reduction(+:x)       
    for (i=0; i<N/2; i++)
    {
        k = N-1-i;
        printf ("\n i = %d ", i);
        printf ("\n k = %d\n", k);
        C[i] = 0;
        C[k] = 0;
        for (j=0; j<N; j++)
        {
            C[i] += MAT[i][j] * B[j];
            C[k] += MAT[k][j] * B[j];
        }
        x += C[i];
        x += C[k];
    } 
    

    所以同一个线程将执行 0 和 N,下一个线程 1 和 N-1...您甚至可以在每个循环的更多执行中分配迭代,但请记住,分配的数量应该是

    如果你想保持顺序:0 N, 1 N-1...你必须使用子句ordered和ordered块但这对并行化没有意义,因为不同的线程并发执行直到它们遇到ordered区域,然后他们以与在串行版本中执行的顺序相同的顺序顺序执行这部分,但增加了线程之间同步的重载时间,您将以较慢的串行版本结束。

        #pragma omp parallel for ordered private (i, j, k) reduction(+:x)
        for (i=0; i<N/2; i++)
        {
                #pragma omp ordered
                k = N-1-i;
                printf ("\n i = %d ", i);
                printf ("\n k = %d\n", k);
                C[i] = 0;
                C[k] = 0;
    
                for (j=0; j<N; j++)
                {
                        C[i] += MAT[i][j] * B[j];
                        C[k] += MAT[k][j] * B[j];
                }
                x += C[i];
                x += C[k];
       }
    

    我认为 N 总是由于您要进行的分配类型,但如果不是这种情况,您可以在 for 之后添加它以执行术语的操作在中间,因为虽然我没有尝试过,但我认为这个 if 顺序它会比并行 for 中消耗的时间更少,因为它是要处理的最后一个元素而且您似乎不想并行化内部循环。

       if(N%2 != 0)
        {
                i = N/2;
                C[i] = 0;
                for (j=0; j<N; j++)
                {
                        C[i] += MAT[i][j] * B[j];
                }
                x += C[i];
        }
    

    【讨论】:

    • 你的答案是错误的。 #pragma omp parallel for private (i, j, k) reduction(+:x) 行不保证任何执行顺序。这是使用您的代码 (N=10) 的打印输出:“ i = 3 k = 6 i = 4 k = 5 i = 0 k = 9 i = 1 k = 8 i = 2 k = 7”
    • @Laci 答案已编辑,是的,正如 VictorEijkhout 所说,由于并行化成本,这个硬件没有意义,但对于了解一点线程分布是一个很好的练习
    • 如果N 是奇数会怎样?请检查您的代码。
    • @Laci 完成,抱歉
    猜你喜欢
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多