练习题1
编写mex函数,函数需要实现如下功能:
统计MATLAB矩阵A中小于等于0的数值个数,函数支持openmp并行,当用户输入输入1时为并行统计,输入0时为串行统计
MATLAB测试代码如下
clc;clear;
M=5000;
N=5000;
A=(randi([-50000,58020],M,N));
matlab_result=0;
tic
for i=1:1:M*N
if(A(i)<=0)
matlab_result=matlab_result+1;
end
end
matlab_t=toc;
fprintf("matlab excution time is %fs\n",matlab_t);
tic
mex_result_serial=csdn_test(A,0);
cpp_serial_t=toc;
fprintf("cpp serial excution time is %fs\n",cpp_serial_t);
tic
mex_result_parallel=csdn_test(A,1);
cpp_para_t=toc;
fprintf("cpp parallel excution time is %fs\n",cpp_para_t);
if(mex_result_parallel==mex_result_serial&&mex_result_parallel==matlab_result)
fprintf("correct\n")
end
mex代码
#include <stdio.h>
#include <stdlib.h>
#include<stack>
#include<omp.h>
#include<mex.h>
#include<ctime>
void mexFunction(int nlhs, mxArray* plhs[],int nrhs, const mxArray* prhs[])
{
#define A_IN prhs[0]
#define Flip_IN prhs[1]
#define Result_out plhs[0]
Result_out = mxCreateDoubleMatrix(1, 1, mxREAL);
double *Result =mxGetPr(Result_out);
*Result=0;
const mwSize *dim_array;
dim_array = mxGetDimensions(A_IN);
double number_ele = 1;
double* A = mxGetPr(A_IN);
double flip = *mxGetPr(Flip_IN);
int dim=mxGetNumberOfDimensions(prhs[0]);
int element=mxGetNumberOfElements(prhs[0]);
if (nrhs != 2)
{
mexErrMsgTxt("Wrong number of input arguments.\n");
}
if (flip==0)
{
for(int i = 0;i<element;++i)
{
if(A[i]<=0)
{
Result[0]+=1;
}
}
}
else
{
int num_t=12;
double result_parallel[num_t]={0};
#pragma omp parallel num_threads(num_t)
{
int num_t=omp_get_num_threads();
int tid=omp_get_thread_num();
int istart=element*tid/num_t;
int iend=element*(tid+1)/num_t;
for (int i=istart;i<iend;++i)
{
if(A[i]<=0)
{
result_parallel[tid]+=1;
}
}
#pragma omp barrier
#pragma omp single
{
for (int i=0;i<num_t;++i)
{
Result[0]+=result_parallel[i];
}
}
}
}
}
本代码设定CPU线程个数为12,具体多少线程时候效率最优与配置有关,好奇的同学可以自己给mex代码添加第三个参数输入接口,测试不同线程个数时候的耗时
#pragma omp barrier和#pragma omp single的原理自行百度,看看就好,并行编程里面常用的时候barrier和single等命令
mex编译指令:
mex C:\ProgramData\MATLAB\SupportPackages\R2020b\3P.instrset\mingw_w64.instrset\lib\gcc\x86_64-w64-mingw32\6.3.0\libgomp.a CXXFLAGS="$CXXFLAGS -std=c++11 -fopenmp" csdn_test.cpp
请根据libgomp.a所在路径自行修改
到本节为止MATLAB+C+Openmp混合编程的基本内容已经结束,暂时停更一段时间~~