将部分与 OpenMP 和 MEX 结合使用

Using sections with OpenMP and MEX

我正在尝试计算 3x3 矩阵逆并将其乘以其他 3x3 矩阵。 这些计算的代码作为 mex 函数工作。 当我尝试使用 OpenMP 库时,我的问题就开始了。 我试图使矩阵逆的两个部分并行,但我遇到了很多编译错误。 评论 pragma 时,代码编译是干净的。 非常感谢您的帮助。

/*==========================================================
 * inv_and_mul_3by3.c
 * inverse 3x3 matrix and multiply it by another 3x3 matrix
 * The calling syntax is: outMatrix = (mat_to_inv,mat_to_mul)
 *========================================================*/

#include "mex.h"
#include <omp.h>

/* The computational routine */
void inv_and_mul_3by3_omp(double *mat_to_mul, double *mat_to_inv, double *out)
{
    // Description : out = inv(mat_to_inv)*mat_to_mul
    double det;
    double det_2by2;
    double det_2by2B;
    double inversed[9];

    // Calculating 2x2 determinant that is being calculated for the 3x3 determinant
    // and also for matrix inversion
    det_2by2  = mat_to_inv[4]*mat_to_inv[8] - mat_to_inv[7]*mat_to_inv[5];
    det_2by2B = mat_to_inv[1]*mat_to_inv[5] - mat_to_inv[4]*mat_to_inv[2];

    /* Calculate the matrix deteminant */
    det = mat_to_inv[0]*(det_2by2) - mat_to_inv[3]*(mat_to_inv[1]*mat_to_inv[8]-mat_to_inv[7]*mat_to_inv[2])+mat_to_inv[6]*(det_2by2B);

        #pragma omp parallel sections
        {

        #pragma omp section {
            // Calcualte the inversed matrix
            inversed[0] = (det_2by2)/det;
            inversed[3] = (mat_to_inv[6]*mat_to_inv[5] - mat_to_inv[3]*mat_to_inv[8])/det;
            inversed[6] = (mat_to_inv[3]*mat_to_inv[7] - mat_to_inv[6]*mat_to_inv[4])/det;
            inversed[1] = (mat_to_inv[7]*mat_to_inv[2] - mat_to_inv[1]*mat_to_inv[8])/det;
        }

       #pragma omp section {
            inversed[4] = (mat_to_inv[0]*mat_to_inv[8] - mat_to_inv[6]*mat_to_inv[2])/det;
            inversed[7] = (mat_to_inv[6]*mat_to_inv[1] - mat_to_inv[0]*mat_to_inv[7])/det;
            inversed[2] = (det_2by2B)/det;
            inversed[5] = (mat_to_inv[3]*mat_to_inv[2] - mat_to_inv[0]*mat_to_inv[5])/det;
            inversed[8] = (mat_to_inv[0]*mat_to_inv[4] - mat_to_inv[3]*mat_to_inv[1])/det;
        }
   } /*-- End of sections block --*/


    // multiply the matrix by the the matrix that was inversed
    out[0] = mat_to_mul[0]*inversed[0] + mat_to_mul[3]*inversed[1] + mat_to_mul[6]*inversed[2];
    out[1] = mat_to_mul[1]*inversed[0] + mat_to_mul[4]*inversed[1] + mat_to_mul[7]*inversed[2];
    out[2] = mat_to_mul[2]*inversed[0] + mat_to_mul[5]*inversed[1] + mat_to_mul[8]*inversed[2];
    out[3] = mat_to_mul[0]*inversed[3] + mat_to_mul[3]*inversed[4] + mat_to_mul[6]*inversed[5];
    out[4] = mat_to_mul[1]*inversed[3] + mat_to_mul[4]*inversed[4] + mat_to_mul[7]*inversed[5];
    out[5] = mat_to_mul[2]*inversed[3] + mat_to_mul[5]*inversed[4] + mat_to_mul[8]*inversed[5];
    out[6] = mat_to_mul[0]*inversed[6] + mat_to_mul[3]*inversed[7] + mat_to_mul[6]*inversed[8];
    out[7] = mat_to_mul[1]*inversed[6] + mat_to_mul[4]*inversed[7] + mat_to_mul[7]*inversed[8];
    out[8] = mat_to_mul[2]*inversed[6] + mat_to_mul[5]*inversed[7] + mat_to_mul[8]*inversed[8];

} //end function

/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[])
{
    double *inMatToInv;             /* 3x3 input matrix that is inversed */
    double *inMatToMul;             /* 3x3 input matrix that multiply the inversed matrix*/
    double *outMatrix;              /* 3x3 output matrix */

    /* create pointers to the real data in the input matrix  */
    inMatToInv = mxGetPr(prhs[0]);
    inMatToMul = mxGetPr(prhs[1]);

    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(3,3,mxREAL);

    /* get a pointer to the real data in the output matrix */
    outMatrix = mxGetPr(plhs[0]);

    /* call the computational routine */
    inv_and_mul_3by3_omp(inMatToInv,inMatToMul,outMatrix);
}

这是我在Matlab中使用的编译命令
mex inv_and_mul_3by3_omp.c COMPFLAGS="/openmp $COMPFLAGS"

以下是编译错误: 使用 mex 时出错 inv_and_mul_3by3_omp.c (32):错误 C3005:“{”:在 OpenMP 上遇到意外标记 'section' 指令
(35):错误 C3047:OpenMP 中的结构化块 'sections' 区域前面必须有“#pragma omp section”
(36):错误 C3047:OpenMP 中的结构化块 'sections' 区域前面必须有“#pragma omp section”
(37):错误 C3047:OpenMP 中的结构化块 'sections' 区域前面必须有“#pragma omp section”
(40):错误 C3005:“{”:在 OpenMP 上遇到意外标记 'section' 指令
(40) : error C3044: 'section' : 只允许直接嵌套 在 OpenMP 'sections' 指令下
(47):错误 C2059:语法错误:“}”
(53):错误 C2065:'mat_to_mul':未声明的标识符
(53) : error C2109: 下标需要数组或指针类型
(53):错误 C2065:'inversed':未声明的标识符
(54) : error C2369: 'out' : 重定义;不同的下标
(53) : 见 'out'
的声明 (54):错误 C2065:'mat_to_mul':未声明的标识符
(54) : error C2109: 下标需要数组或指针类型
(54):错误 C2065:'inversed':未声明的标识符
(55):错误 C2369:'out':重新定义;不同的下标
(53) : 见 'out'
的声明 (55):错误 C2065:'mat_to_mul':未声明的标识符
(55) : error C2109: 下标需要数组或指针类型
(55):错误 C2065:'inversed':未声明的标识符
(56):错误 C2369:'out':重新定义;不同的下标
(53) : 见 'out'
的声明 (56):错误 C2065:'mat_to_mul':未声明的标识符
(56) : error C2109: 下标需要数组或指针类型
(56):错误 C2065:'inversed':未声明的标识符
(57):错误 C2369:'out':重新定义;不同的下标
(53) : 见 'out'
的声明 (57):错误 C2065:'mat_to_mul':未声明的标识符
(57) : error C2109: 下标需要数组或指针类型
(57):错误 C2065:'inversed':未声明的标识符
(58):错误 C2369:'out':重新定义;不同的下标
(53) : 见 'out' 的声明 (58):错误 C2065:'mat_to_mul':未声明的标识符
(58) : error C2109: 下标需要数组或指针类型
(58):错误 C2065:'inversed':未声明的标识符
(59):错误 C2369:'out':重新定义;不同的下标
(53) : 见 'out' 的声明 (59):错误 C2065:'mat_to_mul':未声明的标识符
(59) : error C2109: 下标需要数组或指针类型
(59):错误 C2065:'inversed':未声明的标识符
(60) : error C2369: 'out' : 重定义;不同的下标
(53) : 见 'out' 的声明 (60):错误 C2065:'mat_to_mul':未声明的标识符
(60) : error C2109: 下标需要数组或指针类型
(60):错误 C2065:'inversed':未声明的标识符
(62):错误 C2059:语法错误:'}'

我要做的第一件事是去除嵌套并行性。它并不像许多初学者认为的那样有用,如果不设置编译器 and/or 环境变量,它不一定可用,并且当您应该采取一些小步骤时它正在向前推进。

替换此

#pragma omp parallel
{
    #pragma omp parallel sections num_threads(2)

#pragma omp parallel sections 

并相应地调整其余代码。补充一下我上面写的,尝试指定要使用的线程数通常不是一个好主意,将其留给运行时系统来确定。

我并不假装这是一个完整的答案,而是一个简化代码的步骤,可能有助于阐明错误所在。

尝试替换这个

#pragma omp section {

由此

#pragma omp section 
{