具有特定顺序的线程之间循环迭代的分布

Distribution of loop iterations between threads with a specific order

我有这个系列代码:

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 parallel for 但困难的是分配迭代执行顺序的规范,如:

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

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

我看到的问题是,如果您想像这样分发迭代: 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...您甚至可以将迭代分配到每个循环的更多执行中,但请记住分配的数量应该 <= N

如果你想保留顺序:0 N, 1 N-1...你必须使用子句 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[= 中的一个消耗更少的时间24=] 只是因为它是要处理的最后一个元素,而且您似乎不想并行化内部循环。

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