For the purpose of speeding up the calculation, the project needs to use CUDA to implement some calculations in matlab and then use matlab to call
Since there are too many parameters required in the calculation part, it is too troublesome to transfer them one by one to CUDA, so first use Matlab to store these parameters in the mat file, and read the mat file in the CUDA c++ code.
The final effect is to call the mexw64 file (essentially a dll, the extension name of the linux platform is mexa64) in the Matlab code like a function call.
Since CUDA cannot be used to compile mex directly into mexw64, first use nvcc to compile the cu file into an obj file for mex linking.
Project overall structure
Ø matlabfunction.m - call CUDA's matlab main program
Ø mexmain.cpp - the C++ file that defines mexFunction, and reads the mat file internally, and passes the parameters to CUDA to calculate
Ø kernel.cu - CUDA file, with the definition of the kernel function and a C++ function to receive parameters and call the kernel function to calculate the calculation result
code structure
matlab.m
%matlab performs some data processing %......... % Call the compiled mexw64/mexa64 file, pass in the parameters, and get the calculation result [result1,result2]=MexMain(arg1,arg2) % Processing of calculation results %............
mexmain.cpp
#include "mat.h" #include "mex.h" extern int CUDAFunction(double* arg1, double*arg2);//implemented in the kernel.cu file, the main function is to pass the parameters into the CUDA kernel function and use the GPU for calculation void mexFunction (int nlhs, mxArray * plhs [], int nrhs, const mxArray * prhs []) {//... }
Write the required environment setup on vs
Create a new CUDA project and create a new mexmain.cpp file
Since mexFunction is defined in mexmain.cpp, the mat file is read, and cufft is also called in kernel.cu for fft operation, so add the corresponding include directory and linker input in the vs project properties
Right click project - properties
C/C++-General, additional include directories on the right are added
C:\ProgramFiles\MATLAB\R2017a\extern\include\win64 C:\ProgramFiles\MATLAB\R2017a\extern\include
Linker - General, the additional library directory on the right increases
C:\ProgramFiles\MATLAB\R2017a\extern\lib\win64\microsoft
linker-input, additional dependencies on the right add
libmat.lib libmx.lib libmex.lib libeng.lib cufft.lib
At this point, the project configuration is complete. If vs still prompts that functions or types such as mxArray , mexErrMsgTxt , and matOpen are undefined, you may need to configure environment variables.
add to PATH
C:\ProgramFiles\MATLAB\R2017a\bin\win64 C:\ProgramFiles\MATLAB\R2017a\lib\win64 C:\ProgramFiles\MATLAB\R2017a\extern\lib\win64\microsoft C:\ProgramFiles\MATLAB\R2017a\bin C:\ProgramFiles\MATLAB\R2017a\runtime\win64
(Some are added automatically after installing matlab)
compile
After the code is written, you can start compiling
First use nvcc to compile kernel.cu into an obj file
nvcc -c kernel.cu
This is a simplified command. In actual use, you need to specify the target GPU architecture (parameters such as -arch) and some other parameters. For details, please refer to the introduction of NVCC in the official CUDA document.
C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v8.0\doc
If nvcc has the following error message
nvcc fatal : Cannot find compiler 'cl.exe' in PATH
That's because cl can't be found in the PATH, just add it to it
In vs2015, cl.exe is in
C:\Program Files(x86)\Microsoft Visual Studio 14.0\VC\bin
Then use the mex command in matlab to compile the obj file with the cpp file
mex mexmain.cpp kernel.obj -lCUDArt-lcufft ... -L"C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v8.0\lib\x64" ... -v -I"C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v8.0\include"
Compilation for Linux platform
Since the software will eventually run on Linux, it is not enough to compile the mexw64 file, it needs to be recompiled on Linux
But the process didn't go as smoothly as it did on Windows
Operating system Ubuntu, C++ compiler G++
First, compile the .o file using the same
nvcc -c kernel.cu
then in matlab
mex mexmain.cpp kernel.o -lCUDArt-lcufft ... -L"/usr/local/CUDA-8.0/lib64" ... -v -I"/usr/local/CUDA-8.0/include"
But it prompted the following error
wrong use of mex /usr/bin/ld:kernel.o: relocation R_X86_64_32 against `.bss' can not be used when making ashared object; recompile with-fPIC kernel.o: erroradding symbols: wrong values collect2: error: ld returned 1
Simply put, the kernel.o file compiled by kernel.cu is not address-independent. To use the -fPIC option to recompile, the shared library (.so file) must be compiled with -fPIC under Linux.
The way to use the -fPIC option in nvcc is to use --compiler-options-fPIC
so use
nvcc -c--compiler-options -fPIC kernel.cu
Compile the kernel.o and then use the mex command to successfully compile the mexa64 file
References for problems
CUDA8 + VS2015 corecrt.h error