性能:在列上有效减少2d阵列[OpenMP,C]

时间:2017-12-09 11:28:52

标签: c arrays performance openmp

我想实现非常有效的并行缩减操作(即求和):二维数组的每一列(行中的内存缓冲区)应该与一维数组的条目相加。 / p>

更清楚预期的输入和输出

double* array = malloc(sizeof(double) * shape0 * shape1) /* (shape0*shape1) 2-d array */
double* out = malloc(sizeof(double) * shape1) /* where out[j] = sum_j(array_ij) */

并行化行的总和是非常简单和有效的,因为这些值在内存中是连续的,并且没有竞争条件的风险。我发现这个效果很好

void sum_rows(double* array, int shape0, int shape1, double* out) {
    int i, j;
    #pragma omp parallel for private(j) schedule(guided) 
    for (i=0; i < shape0; i++){
        for (j=0; j < shape1; j++){
            out[i] += array[shape1 * i + j];
        }
    }
}

我发现在另一个轴上进行并行化更加困难。 这应该是一个简单的平行配方,但我无法找到一个明确的答案是什么是最有效的编程方式。

这是我想编写高效并行版本的天真串行代码:

void sum_columns(double* array, int shape0, int shape1, double* out) {
    int i, j;
    for (i=0; i < shape0; i++){
        for (j=0; j < shape1; j++){
            out[j] += array[shape1 * i + j];
        }
    }
}

注意: 我已经阅读了以下q / a但它们并没有让我对天真的顺序代码有任何加速:

Parallelizing matrix times a vector by columns and by rows with OpenMP

OpenMP average of an array

Reduction with OpenMP

1 个答案:

答案 0 :(得分:1)

报告一些尝试后我能够实现的更快的实现。在这里,我将列分配给不同的线程,以这种方式尽可能在本地工作并避免错误共享。

void sum_columns(double* array, int N_rows, int N_cols, double* out, int n_threads) {
    omp_set_dynamic(0);
    omp_set_num_threads(n_threads);
    #pragma omp parallel
    {
        /* private vars */
        int i, j, id, N_threads, col_chunk_size, start_col, end_col;
        /* ICVs */
        id = omp_get_thread_num();
        N_threads = omp_get_num_threads();
        /* distribute cols to different threads */
        col_chunk_size = N_cols / N_threads;
        start_col = id * col_chunk_size;
        end_col = (id+1) * col_chunk_size;
        if (id == N_threads - 1) end_col = N_cols;

        /* main loop */
        for (i=0; i < N_rows; i++){
            for (j=start_col; j < end_col; j++){
                out[j] += array[N_cols * i + j];
            }
        }
    }
 }