Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
性能:在列上有效减少2d阵列[OpenMP,C]_C_Arrays_Performance_Openmp - Fatal编程技术网

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

性能:在列上有效减少2d阵列[OpenMP,C],c,arrays,performance,openmp,C,Arrays,Performance,Openmp,我希望实现非常高效的并行缩减操作(即求和):二维数组(行内存布局中的内存缓冲区)的每一列都应求和为一维数组的一个条目 更清楚地了解预期的输入和输出 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) */ 并行化

我希望实现非常高效的并行缩减操作(即求和):二维数组(行内存布局中的内存缓冲区)的每一列都应求和为一维数组的一个条目

更清楚地了解预期的输入和输出

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_行(double*数组、int-shape0、int-shape1、double*out){
int i,j;
#pragma omp并行专用(j)时间表(指南)
对于(i=0;i
我发现在另一个轴上平行比较困难。 这应该是一个简单的平行配方,但我无法找到一个明确的答案,什么是最有效的编程方法

这是我想要编写的高效并行版本的简单串行代码:

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];
        }
    }
}
void sum_列(双*数组、整数形状0、整数形状1、双*输出){
int i,j;
对于(i=0;i
注: 我已经阅读了以下q/a,但它们并没有让我对天真的顺序代码有任何加速:


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

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];
            }
        }
    }
 }
void sum_列(double*数组、int N_行、int N_列、double*out、int N_线程){
omp_集_动态(0);
omp_集合_num_线程(n_线程);
#pragma-omp并行
{
/*私人骑兵*/
int i、j、id、N线程、列块大小、开始列、结束列;
/*ICV*/
id=omp_get_thread_num();
N_threads=omp_get_num_threads();
/*将COL分配到不同的线程*/
col_chunk_size=N_cols/N_线程;
开始列=id*列块大小;
结束列=(id+1)*列块大小;
如果(id==N\u threads-1)end\u col=N\u cols;
/*主回路*/
对于(i=0;i
显然,您可能忽略了有关如何为内部循环减少simd的“权威”文档。它也取决于编译器和选项。如果需要提示,你需要SIMD内联来优化微软编译器,但是使用现代编译器很容易。如果使用现代C++,应该考虑InnEnEngultTuffes()。我也会拒绝你的BLA拒绝,因为没有明确的文档。我之前的评论假设你不想绕过openmp。我可能表达得非常糟糕。。。我觉得我在这里被误解了。我只是想找到一个问题的解决方案,我认识到,对于每天使用openmp的人来说,这个问题可能微不足道,在谷歌搜索之后,我对没有找到解决方案表示惊讶。无意作判断。。。只是要求一个解决方案。