Matlab调用Cuda程序

2023-05-16

目录

一. 环境配置

1. GPU+VisualStudio+Matlab版本适配性查看

2. Matlab环境配置

二. 使用Matlab编译CUDA工程

1. 建立CUDA工程并编写GPU代码

2. 编写可供Matlab编译的CUDA代码

2.1 包含的头文件

2.2 程序入口函数mexFunction

3. 使用Matlab编译CUDA工程并调用

3.1 mexcuda编译指令 

3.2 调用方法


总结一下之前做的工作,想到哪里写到哪里,以后遇到问题会继续更新~~~~

———————————————————以下为正式内容—————————————————

一. 环境配置

1. GPU+VisualStudio+Matlab版本适配性查看

        查看本机matlab支持的vs版本信息:Matlab安装路径\bin\win64\mexopts

        查看本机Matlab支持哪个版本的GPU:GPU Support by Release- MATLAB & Simulink- MathWorks 中国https://ww2.mathworks.cn/help/parallel-computing/gpu-support-by-release.html

2. Matlab环境配置

        首先在matlab命令行输入

mex -setup C++

        使用适合本机的Vs编译Cuda程序

二. 使用Matlab编译CUDA工程

1. 建立CUDA工程并编写GPU代码

1.1  点击VisualStudio图标,点击创建新项目

1.2. 选择CUDA 11.3 Runtime(11.3为本机安装的CUDA ToolKit版本)

1.3. 编写GPU代码。

1.4 几点建议

        (1)为了便于确定代码执行的正确性,建议先用一般的c语言标准编写代码并验证正确性 。

        (2)编写头文件时,规范使用#ifdef、#define、#endif防止头文件嵌套包含时的重复调用,不建议使用#pragma once,因为#ifdef、#define、#endif受C/C++语言标准支持,不受编译器的限制,而#pragma once受编译器的限制,mexcuda编译器不一定支持#pragma once。

#ifndef _HeadFileName_H // _HeadFileName为当前头文件的名称
#define _HeadFileName_H

/*** 头文件内容 ***/

#endif

        (3)在核函数中使用pow函数时,最好使用powf(CUDA内置的加速函数)代替,防止后续Matlab端编译错误

        (4)如果在代码中使用了动态并行,需要将属性-> CUDA C/C++ -> Generate Relocatable Device Code设置为 是(-rdc=true)

2. 编写可供Matlab编译的CUDA代码

2.1 包含的头文件

        在项目中添加新建项 mexFunction.h,头文件内容如下

#ifndef _mexFunction_H
#define _mexFunction_H

#include "MatlabPath\extern\include\mex.h"
#include "MatlabPath\toolbox\parallel\gpu\extern\include\gpu\mxGPUArray.h"

#endif

        MatlabPath是本机Matlab的安装目录,需要注意的是,因为matlab版本的更新,mex和mxGPUArray的文件路径可能与上述不符,此时在Matlab安装目录中搜索mex.h和mxGPUArray.h,将搜索结果所在的路径复制过来即可。

2.2 程序入口函数mexFunction

 与c语言不同,使用Matlab编译代码时的程序入口函数为mexFunction函数,函数定义规范为

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{

    /**** 程序内容 ****/		

}

        文件中需要包含2.1中定义的“mexFunction.h”头文件。

1.接口参数定义

参数名称参数含义
nlhs输出变量个数
plhs输入变量指针数组
nrhs输入变量个数
prhs输入变量指针数组

 2.参数传递方法为

(1)获取实数输入变量

//获取实数指针
AfterRvpDataReal = (float*)mxGetPr(prhs[0]);// float或int或double

(2)获取复数输入变量

//获取实部指针
double* real = (double*)mxGetPr(prhs[0]);

//获取虚部指针:
double* imag = (double*)mxGetPi(prhs[0]);

(3)获取字符串输入变量

        需要使用mxArrayToString对输入变量类型进行转化。

char* path = mxArrayToString(prhs[5]);

(4)获取矩阵大小

//输入矩阵的行数
row = mxGetM(prhs[0]);

//输入矩阵的列数
column = mxGetN(prhs[0]);

(5)初始化实数输出变量

plhs[0] = mxCreateNumericMatrix(DistanceNum*AzimuthNum, 1, mxSINGLE_CLASS, mxREAL);

real = (float*)mxGetPr(plhs[0]);

plhs[1] = mxCreateNumericMatrix(DistanceNum*AzimuthNum, 1, mxSINGLE_CLASS, mxREAL);

imag = (float*)mxGetPr(plhs[1]);

(6)初始化复数输出变量

plhs[0] = mxCreateNumericMatrix(rawNum, columnNum, mxSINGLE_CLASS, mxCOMPLEX);

real = (float*)mxGetPr(plhs[0]);

imag = (float*)mxGetPi(plhs[0]);

假设是2*5矩阵(rawNum = 2,columnNum = 5)

real[6] = {1,2,3,4,5,6,7,8,9,10};imag[6] = {1,3,5,7,9,11,13,15,17,19}

则传回matlab的矩阵是:

(7)一个例程:

void mexFunction(int nlhs, mxArray *plhs[],

    int nrhs, mxArray const *prhs[])

{

    double* a = (double*)mxGetPr(prhs[0]);

    double* b = (double*)mxGetPi(prhs[0]);

    int c = mxGetM(prhs[0]);

    double* real;

    double* image;

    plhs[0] = mxCreateNumericMatrix(2, 5, mxDOUBLE_CLASS, mxCOMPLEX);

    real = (double*)mxGetPr(plhs[0]);

    image = (double*)mxGetPi(plhs[0]);

    for (int i = 0; i < 10; i++)

    {
        real[i] = i;

        image[i] = 2 * i + 1;
    }

    printf("------------------\n");

    printf("%f,%f,%f,%f\n", a[0],a[1],a[2],a[3]);

    printf("%f,%f,%f,%f\n", b[0], b[1], b[2], b[3]);

    printf("%d\n",c);

    printf("------------------");

}

3. 使用Matlab编译CUDA工程并调用

3.1 mexcuda编译指令 

Matlab编译CUDA工程使用mexcuda指令,该指令的说明文档在

Compile MEX-function for GPU computation - MATLAB mexcuda - MathWorks 中国https://ww2.mathworks.cn/help/parallel-computing/mexcuda.html接下来对该指令的应用进行简单的说明。

(1)如果工程中有多个源文件option1,option2,……,optionN,则需要输出使用到的所有源文件的路径,此处建议输入文件的完整路径(绝对路径),而非相对路径,例如:

mexcuda E:\Work\cudaSource1.cu E:\Work\cudaSource2.cu E:\Work\cSource1.cpp... 
E:\Work\cSource2.cpp

(2)如果文件中使用了动态并行,则需要在对应的文件前面加上-dynamic,例如:

mexcuda -dynamic E:\Work\cudaDynamicSource1.cu ...
E:\Work\cudaNoDynamicSource2.cu ...
-dynamic E:\Work\cudaDynamicSource3.cu ...
E:\Work\cSource1.cpp ...

 (3) 如果文件中使用了CUDA库函数(cufft、cublas等),则需要加入库函数路径,格式是

‘库函数完整文件路径’ -l+库函数名称,例如:

mexcuda  'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\lib\x64\cufft.lib' -lcufft ...
-dynamic E:\Work\cudaDynamicSource1.cu ...
E:\Work\cudaNoDynamicSource2.cu ...
-dynamic E:\Work\cudaDynamicSource3.cu ...
E:\Work\cSource1.cpp ...

(4)按回车后,出现MEX已成功完成证明编译成功,此时文件夹中应该出现.mexw64执行文件,该文件名称与mexcuda指令后的第一个文件名保持一致,例如,(3)中生成的文件名称为cudaDynamicSource1.mewx64。

 (5) 可能出现的问题以及修正方法

  • 调用的子函数中的printf函数无法正常打印内容

        解决方法:将printf函数更换为mexPrintf函数,使用时同样需要包含头文件"mex.h"和"mxGPUArray.h"两个头文件,即2.1中定义的“mexFunction.h”头文件。

  • 错误信息:无法解析的外部符号 mexFunction
    错误使用 mex
    LINK : error LNK2001: 无法解析的外部符号 mexFunction
    ConfidencePixelSelection.lib : fatal error LNK1120: 1 个无法解析的外部命令

    出现原因:没有编写mexFunction程序入口

        改正方法:按照 2. 编写可供Matlab编译的CUDA代码 中的方法编写mexFucntion函数

  • 错误信息:undefine reference to '_Z3powfi'
    nvlink error   : Undefined reference to '_Z3powfi' in 'C:/Users/lenovo/AppData/Local/Temp/mex_374451651535793_20720/MatrixOperation.obj' (target: sm_35)

        出现原因:在核函数中使用了cpu函数pow()

        改正方法:将核函数中的pow改为powf

  • 错误信息:redefine/无法重载仅以返回类型区分的函数

        出现原因:头文件重复定义

        改正方法:在头文件开头和结尾加入:#ifndef,#define,#endif

  • 错误信息:
F:\HSCdownload\Matlab\R2020b\extern\include\matrix.h(756): error C2143: 语法错误: 缺少“)”(在“常数”的前面)
F:\HSCdownload\Matlab\R2020b\extern\include\matrix.h(756): error C2143: 语法错误: 缺少“;”(在“常数”的前面)
F:\HSCdownload\Matlab\R2020b\extern\include\matrix.h(756): error C2059: 语法错误:“常数”
F:\HSCdownload\Matlab\R2020b\extern\include\matrix.h(757): error C2059: 语法错误:“)”

        出现原因:具体的咱也不清楚

        改正方法:把“mex.h”和“mxGPUArray.h”的头文件包含放在自定义头文件的前面,例如:将下方代码段

  • //标准库部分
    #include <stdio.h>
    #include <stdlib.h>
    
    //自定义头文件
    #include "a.h"
    
    //mexFuntion头文件
    #include "F:\HSCdownload\Matlab\R2020b\extern\include\mex.h"
    #include "F:\HSCdownload\Matlab\R2020b\toolbox\parallel\gpu\extern\include\gpu\mxGPUArray.h"

    改为:

    //标准库部分
    #include <stdio.h>
    #include <stdlib.h>
    
    //mexFuntion头文件
    #include "F:\HSCdownload\Matlab\R2020b\extern\include\mex.h"
    #include "F:\HSCdownload\Matlab\R2020b\toolbox\parallel\gpu\extern\include\gpu\mxGPUArray.h"
    
    //自定义头文件
    #include "a.h"
    
  • 错误信息

error C2059: 语法错误:“<”

        出现原因:出现错误的位置是核函数调用时候的<<<  >>>,所以是因为在c/c++文件中调用了核函数

        改正方法:对应的文件由.cpp改为.cu即可

3.2 调用方法

调用mexw64文件的方法与函数调用方法相同,但是要注意,如果cuda代码中的参数精度为float、int等,需要先在matlab中进行类型转化,转化方法为:

单精度参数:single(var)

整型参数:int32(var)

将参数传回matlab端后,需要使用gather()函数将结果转化为matlab中的数据类型以便进行后续处理。

% 调用cudaDynamicSource1.mmexw64程序
% cuda代码中matInPutVar1为双精度类型,matInPutVar2为单精度类型,matInPutVar3为整型
cudaInPutVar1 = matInPutVar1;
cudaInPutVar2 = single(matInPutVar2);
cudaInPutVar3 = int32(matInPutVar3);
[cudaOut1, cudaOut2] = cudaDynamicSource1(cudaInPutVar1 , cudaInPutVar2 , cudaInPutVar2 );

% 将cuda输出转化为Matlab的数据类型
matOut1 = double(gather(cudaOut1);
matOut2 = double(gather(cudaOut2);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Matlab调用Cuda程序 的相关文章

  • opencv中矩阵的超快中值(与matlab一样快)

    我正在 openCV 中编写一些代码 想要找到一个非常大的矩阵数组 单通道灰度 浮点数 的中值 我尝试了几种方法 例如对数组进行排序 使用 std sort 和选择中间条目 但与 matlab 中的中值函数相比 它非常慢 准确地说 在 ma
  • 将组合字符串和数字输入的元胞数组写入文本文件

    考虑以下 DateTime 2007 01 01 00 00 2007 02 01 00 00 2007 03 01 00 00 Headers Datetime Data Dat 100 200 300 Data DateTime num
  • 类方法的自定义代码完成?

    在 MATLAB 中 可以定义代码建议和完成 如标题为 的文档页面中所述 自定义代码建议和完成 https www mathworks com help matlab matlab prog customize code suggestio
  • 傅里叶变换定理 matlab

    我目前正在尝试理解二维傅里叶位移定理 根据我到目前为止所了解到的情况 图像空间中的平移会导致相位差异 但不会导致频率空间中的幅度差异 我试图用一个小例子来演示这一点 但它只适用于行的移位 而不适用于列的移位 这是一个小演示 我只在这里显示幅
  • CUDA、NPP 滤波器

    CUDA NPP 库支持使用 nppiFilter 8u C1R 命令过滤图像 但不断出现错误 我可以毫无问题地启动并运行 boxFilterNPP 示例代码 eStatusNPP nppiFilterBox 8u C1R oDeviceS
  • Matlab Solve():未给出所有解决方案

    我试图找到两条曲线的交点 syms x y g x 20 exp x 30 3 5 1 sol x sol y solve x 22 3097 2 y 16 2497 2 25 y g x x y Real true 它只提供一种解决方案
  • 如何在Matlab中将世界坐标转换为像素索引

    我有 512x512x313 体积的 dicom 图像 并且我有一个以世界坐标表示的点 57 7475 63 4184 83 1515 我如何在 Matlab 中获得该世界坐标的相应像素坐标 我不想戳破你的幻想 但你所要求的是不可能的 我能
  • 定义自定义 Mupad 程序的一般相对搜索路径

    假设我有一个 mupad 笔记本myMupadNotebook mn在路径上 C projectFolder ABC abc 它调用程序MyMupadProcedure mu它位于 C DEF GHI 现在我有一个 Matlab 脚本mai
  • 如何加载具有可变文件名的 .mat 文件?

    select all mat files oar dir oar mat n oar name loop through files for l 1 length oar load pat oar l lt this is the mat
  • 如何获取MATLAB句柄对象的ID?

    当我尝试使用时出现问题MATLAB 句柄对象 http www mathworks com help techdoc ref handle html作为关键值MATLAB 容器 Map http www mathworks com help
  • 归一化互相关的基础知识

    我正在尝试使用范数校正2 归一化互相关 http en wikipedia org wiki Cross correlation Normalized cross correlation 来自 MATLAB 用于计算发育中胚胎中移动形状的速
  • 垂直子图的单一颜色条

    我想让下面的 MATLAB 图有一个沿着两个子图延伸的颜色条 像这样的事情 使用图形编辑器手动完成 Note 这与提出的问题不同here https stackoverflow com questions 39950229 matlab t
  • 如何为已编译的 MATLAB 创建安装程序并要求用户接受我们的许可条款?

    我正在 MATLAB 中编写程序分发给 Windows 用户 我使用 MATLAB 编译器和 MATLAB r2014a 版本来创建程序 我可以使用 MATLAB 应用程序编译器创建 Windows 安装程序 并且它的工作效果可以接受 但是
  • 如何在Matlab中绘制网络?

    我有一个矩阵AMatlab中的维数mx2每行包含两个节点的标签 显示网络中的直接链接 例如 如果网络有4矩阵的节点A可能A 1 2 1 3 2 1 2 4 3 2 4 1 4 2 其中第一行表示有一个链接来自1 to 2 第二行表示有一个链
  • 如何在向量中的所有点之间绘制线?

    我有一个包含二维空间中一些点的向量 我希望 MATLAB 用从每个点到每个其他点绘制的线来绘制这些点 基本上 我想要一个所有顶点都连接的图 你能用情节来做到这一点吗 如果可以 怎么做 一种解决方案是使用该函数为每个点组合创建一组索引MESH
  • Matlab 一个图上有多个图例 2014b

    我想在一个地块上有多个传说 该解决方案在 2014b 版本之前完美运行 我试图弄清楚如何使用手柄优雅地制作它 但到目前为止还没有成功 欢迎任何想法 2013b 的示例 x 1 50 y1 sin x 2 y2 cos x 2 f figur
  • 无法在内存位置找到异常源:cudaError_enum

    我正在尝试确定 Microsoft C 异常的来源 test fft exe 中 0x770ab9bc 处的第一次机会异常 Microsoft C 异常 内存位置 0x016cf234 处的 cudaError enum 我的构建环境是 I
  • 如何在Matlab中打印带有千位分隔符的整数?

    我想使用逗号作为千位分隔符将数字转换为字符串 就像是 x 120501231 21 str sprintf 0 0f x 但随着效果 str 120 501 231 21 如果内置fprintf sprintf做不到 我想可以使用正则表达式
  • Matlab 图像数据的 hist 函数

    我是 Matlab 新手 我想制作自己的函数 与 imhist 显示图像数据的直方图 完成相同的工作 但我对此完全是新手 我不知道如何做开发这样的功能 我开始做一些东西 但它非常不完整 function output args myhist
  • Matlab:条形图中缺少标签

    使用 Matlab 2012 和 2013 我发现设置XTickLabel on a bar图表最多只能使用 15 个柱 如果条形较多 则标签会丢失 如下所示 绘制 15 个条形图 N 15 x 1 N labels num2str x d

随机推荐

  • CentOS7安装vncserver

    1 关闭防火墙和selinux systemctl stop firewalld service setenforce 0 2 安装图形支持 yum groups install 34 GNOME Desktop 34 或yum group
  • Echarts tooltip加上单位并带着图例颜色

    模仿腾讯疫情地图 xff0c Y轴有个百分比 xff0c 也就是Y轴有单位 xff0c 使用JS代码如下 xff1a tooltip trigger 39 axis 39 formatter function params var relV
  • xv6调试

    窗口1作为xv6的运行窗口 make CPUS 61 1 qemu gdb 窗口2作为gdb调试窗口 gdb multiarch kernel kernel 进入gdb后执行 set confirm off set architecture
  • mit6.s081-21-Lab1/ Xv6 and Unix utilities

    sleep Implement the UNIX program sleep for xv6 your sleep should pause for a user specified number of ticks A tick is a
  • Python+scrcpy+pyminitouch实现自动化(四)——实现语音识别自动打卡机器人

    首先要去网上下载一个想要实现自动化的软件 xff0c 下载对应的apk后拖拉到虚拟器的页面即可实现自动下载 以上是对于AS打开的模拟器进行的下载安装 xff0c 由于我找不到关于x86的企业微信 xff0c 所以我就换了逍遥模拟器 xff0
  • CMU15445 lab1 - BUFFER POOL

    本文为本人完成15445 2020fall B 43 树版本 时的一些记录 xff0c 仅作为备忘录使用 TASK 1 LRU REPLACEMENT POLICY 本任务为实现一个LRU页面置换策略 xff0c 建立一个关于面向磁盘的数据
  • 医院信息管理系统(Python与MySQL数据库的连接与相关增删改查操作)

    题目意义 医院信息管理是一项琐碎 复杂而又十分细致的工作 xff0c 这关系到医院体系能否运行起来这一关乎国民健康水平的重大问题 我们只有利用好了医院中每个医生 护士的各项资源 xff0c 才能使得医院系统能够有序而条理的进行 xff0c
  • 慢速协议-Slow Protocol-LACP

    慢速协议有三种 xff0c 包括802 3ah OAM LACP协议和Marker协议 慢速协议的特点 xff1a 1 xff0c 每秒钟传输的报文不超过10帧 xff1b 2 xff0c 报文不携带vlan tag xff1b 3 xff
  • fork() && fork() || fork()

    include lt unistd h gt include lt stdio h gt int main fork fork amp amp fork fork fork sleep 100 return 0 问题是不算main这个进程自
  • list_entry()详解

    Linux内核中 xff0c 获取节点地址的函数list entry 非常常用 xff0c 由于其定义有点晦涩 xff0c 先解析如下 xff1a list entry的宏定义 xff1a define list entry ptr typ
  • Linux 内核 hlist 详解

    在Linux内核中 xff0c hlist xff08 哈希链表 xff09 使用非常广泛 本文将对其数据结构和核心函数进行分析 和hlist相关的数据结构有两个 xff1a hlist head 和 hlist node hash桶的头结
  • 判断手机号码合法性

    问题描述 xff1a 我国大陆运营商的手机号码标准格式为 xff1a 国家码 43 手机号码 xff0c 例如 xff1a 8613912345678 特点如下 xff1a 1 长度13位 xff1b 2 以86的国家码打头 xff1b 3
  • linux c捕获信号

    linux c捕获信号 在程序中为了实现优雅退出 xff0c 需要对信号进行处理 xff0c 本文主要记录一下两个方面 xff1a 如何捕获SIGINT SIGTERM SIGQUIT等信号 xff0c 并进行处理 如何知道是哪个进程给自己
  • go语言获取发送信号的进程pid

    背景 今天在发布一个程序之前 xff0c 给qa提测的时候 xff0c qa反馈程序运行10几分钟之后 xff0c 退出了 排查过程 在程序中加日志 xff0c 发现程序捕获到了一个SIGTERM信号 xff0c 然后做了一些退出前的清理工
  • ubuntu-E:Encountered a section with no Package: header的解决办法

    刚才打开ubuntu xff0c 我的版本是12 04 正想使用sudo apt get install build essential 时 xff0c 出现了如下错误 xff1a E Encountered a section with
  • scrcpy源码阅读及在Ubuntu上的实现(一)——了解原理

    那开篇就问问为什么需要研究这个源码吧 xff1a 在移动互联网的时代下 xff0c 手机的功能是日益增加的 xff0c 要使工作变得更加的高效 xff0c 那么键盘鼠标其实是必不可少的 在许多软件的架构中 xff0c 其实并没有提供对应的桌
  • 文件或目录损坏且无法读取的解决办法

    方法很简单 用 chkdsk 命令即可 详解如下 开始 运行 输入 cmd 输入 chkdsk 盘符 f 等命令运行完即可 这里要注意的是 那个冒号后面要空一格 别跟着就写 34 f 34
  • Linux技巧-如何查看系统信息-硬盘、分区信息以及磁盘用量

    使用 hdparm 获得硬盘的生产厂家 xff0c 类型等基本信息 xff0c 这里我们之提供简单的使用 xff0c 以后 hdparm i dev sda 通过 smartctl命令来获取硬盘的详细信息 xff1a smartctl a
  • 朋友答App技术服务支持

    朋友答App有任何使用问题 xff0c 欢迎留言交流
  • Matlab调用Cuda程序

    目录 一 环境配置 1 GPU 43 VisualStudio 43 Matlab版本适配性查看 2 Matlab环境配置 二 使用Matlab编译CUDA工程 1 建立CUDA工程并编写GPU代码 2 编写可供Matlab编译的CUDA代