使用 OpenMP 进行缩减:矩阵/张量运算示例

问题描述 投票:0回答:1

我正在尝试学习如何在 OpenMP 中使用归约,并且想知道是否可以使用归约来重写以下示例?

示例 A:求三个矩阵/张量的和

#include <Eigen/Dense>
#include <Eigen/SparseCore> 
#include <Eigen/Sparse>
static const int nx = 128; 
static const int ny = 128; 
static const int nz = 128;

Eigen::Tensor<std::complex<double>, 3> Tensor1(nx,ny,nz);   
Eigen::Tensor<std::complex<double>, 3> Tensor2(nx,ny,nz);    
Eigen::Tensor<std::complex<double>, 3> Tensor3(nx,ny,nz); 
for(int i = 0; i< nx; i++){
        for(int j = 0; j< ny; j++){
            for(int k = 0; k< nz; k++){ 
                Sum(k,i,j) = (Tensor1(k,i,j) + Tensor2(k,i,j) + Tensor3(k,i,j));

            }
        }
    }

示例 B:求 (AxB) 叉积的单独项:

#include <Eigen/Dense>
#include <Eigen/SparseCore> 
#include <Eigen/Sparse>
static const int nx = 128; 
static const int ny = 128; 
static const int nz = 128;

double B[3] = {Bx,By,Bz};

Eigen::Tensor<std::complex<double>, 3> Ax(nx,ny,nz);  
Eigen::Tensor<std::complex<double>, 3> Ay(nx,ny,nz); 
Eigen::Tensor<std::complex<double>, 3> Az(nx,ny,nz); 

Eigen::Tensor<std::complex<double>, 3> Termx(nx,ny,nz);   
Eigen::Tensor<std::complex<double>, 3> Termy(nx,ny,nz);    
Eigen::Tensor<std::complex<double>, 3> Termz(nx,ny,nz);    

    for(int i = 0; i< nx; i++){
        for(int j = 0; j< ny; j++){
            for(int k = 0; k< nz; k++){ 
                    Termx(k,i,j) = (Az(k,i,j) * By - Ay(k,i,j) * Bz);
                    Termy(k,i,j) =  (Ax(k,i,j) * Bz - Az(k,i,j) * Bx);
                    Termz(k,i,j) =  (Ay(k,i,j) * Bx - Ax(k,i,j) * By);


            }
        }
    }
    

我还没有看到使用嵌套循环或矩阵/张量进行归约的示例,因此我不确定上述示例是否适用于归约。谢谢!

c++ openmp eigen eigen3
1个回答
0
投票

简短的回答是否定的。

更长的答案是你的例子不符合减少的目的的基本思想。

缩减通常用于所有线程写入单个输出的情况。对于一个非常简单的例子,考虑标准化一个大矩阵,只需将所有数字相加,然后将每个数字除以总和,使它们都在 0..1.

范围内
#pragma omp parallel for
for (int i=0; i<n; i++)
    for (int j=0; j<m; j++)
        for (int k=0; k<o; k++)
            sum += matrix[i][j][k];

这有一个问题:所有线程都写入

sum
。为了保持有意义的结果,OpenMP 运行时序列化对
sum
的访问,并且我们从并行运行的所有线程中获得的收益非常少(如果有的话)。

我们可以使用

reduction
来解决这个问题:

#pragma omp parallel for reduction(+:sum)
for (int i=0; i<n; i++)
    for (int j=0; j<m; j++)
        for (int k=0; k<o; k++)
            sum += matrix[i][j][k];

这样,每个线程都会获得一个私有变量,用于存储其本地总和。然后,当线程完成时,它会进行归约(在本例中使用我们指定的运算符 -

+
)并将所有这些单独的值加在一起。

reduction
当所有线程一起工作以生成单个值时会有所帮助,并且我们可以通过让每个线程独立生成一个值,然后组合所有这些独立值来避免该值的压力。

© www.soinside.com 2019 - 2024. All rights reserved.