Generate Code by Using the GPU Coder App
This example shows how to generate CUDA® code from a MATLAB® function by using GPU Coder™. The entry-point function is a MATLAB implementation of the Mandelbrot set algorithm. This example uses the GPU Coder app to check for run-time issues in the generated code and to generate a MEX function that can run on a GPU. For an example that shows how to generate code programmatically, see Generate Code Using the Command Line Interface.
Verify the GPU Environment
This example generates a CUDA MEX function and requires a CUDA-enabled NVIDIA® GPU and compatible driver. For more information, see Setting Up the Prerequisite Products.
To verify that the compilers and libraries necessary to run this example are set up correctly, use the coder.checkGpuInstall
function:
envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
coder.checkGpuInstall(envCfg);
Compatible GPU : PASSED CUDA Environment : PASSED Runtime : PASSED cuFFT : PASSED cuSOLVER : PASSED cuBLAS : PASSED Host Compiler : PASSED Basic Code Generation : PASSED
The output above is an example of a call to coder.checkGpuInstall
. The output may be different when you run this code.
Mandelbrot Entry-Point Function
The Mandelbrot set is the region in the complex plane that consists of the values for which the trajectories defined by
remain bounded at . The figure shows the overall geometry of the Mandelbrot set. This view does not have the resolution to show the detailed structure of the fringe outside the boundary of the set.
The mandelbrot_count.m
entry-point function contains a vectorized implementation of the Mandelbrot set based on the code provided in Experiments with MATLAB by Cleve Moler.
type mandelbrot_count.m
function count = mandelbrot_count(maxIterations,xGrid,yGrid) %#codegen % Copyright 2016-2024 The MathWorks, Inc. z0 = complex(xGrid, yGrid); count = ones(size(z0)); % Map computation to GPU. coder.gpu.kernelfun; z = z0; for n = 0:maxIterations z = z.*z + z0; inside = abs(z)<=2; count = count + inside; end count = log(count);
The entry-point function contains the coder.gpu.kernelfun
pragma to map the computation inside the function to a CUDA kernel. The %#codegen
directive inside mandelbrot_count
causes MATLAB to check the function for warnings and errors related to code generation.
Test the Functionality of the Entry-Point Function
The mandelbrot_test.m
script generates a 1000-by-1000 grid of real and imaginary parts between the limits xlim
and ylim
. It calls mandelbrot_count
with this grid and plots the resulting Mandelbrot set.
type mandelbrot_test.m
% Copyright 2024 The MathWorks, Inc. maxIterations = 500; gridSize = 1000; xlim = [-0.748766713922161,-0.748766707771757]; ylim = [0.123640844894862,0.123640851045266]; x = linspace(xlim(1),xlim(2),gridSize); y = linspace(ylim(1),ylim(2),gridSize); [xGrid,yGrid] = meshgrid(x,y); %% Mandelbrot computation in MATLAB count = mandelbrot_count(maxIterations,xGrid,yGrid); %% Show figure(1) imagesc(x,y,count); colormap([jet();flipud(jet());0 0 0]); axis off title('Mandelbrot set with MATLAB');
Run the mandelbrot_test
script to plot the Mandelbrot set in the boundaries of xlim
and ylim
.
mandelbrot_test
Generate Code with the GPU Coder App
In the MATLAB Toolstrip, in the Apps tab, click GPU Coder to open the app. Alternatively, open the app by entering gpucoder
at the MATLAB command line:
gpucoder
The app opens the Select tab. Enter the name of the primary function, mandelbrot_count
. The app creates a project with the name mandelbrot_count.prj
in the current folder.
When you click Next, the app runs the code generation readiness tool. The tool screens the MATLAB code for features and functions that do not support code generation. The app then opens the Review Code Generation Readiness page if it detects issues. In this example, the GPU Coder App does not detect code generation readiness issues. Click Next to proceed to the Define Input Types step.
Define Input Types
GPU Coder must determine the data types of the variables in your MATLAB code before it generates code. Therefore, you must specify the data types of the input variables for your entry-point functions on the Define Input Types page. You can specify the input data types by providing a file that calls the entry-point functions in your project or by entering the input data types manually in the app.
In this example, mandelbrot_test
calls the entry-point function mandelbrot_count
. Enter the test file mandelbrot_test
and click Autodefine Input Types.
Click Next to go to the Check for Run-Time Issues page.
Check for Run-Time Issues
The Check for Run-Time Issues page generates a MEX file from your entry-point functions, runs the MEX function, and reports issues. This step is optional. However, you can use this step to detect and fix defects that are harder to diagnose in the generated GPU code.
Click the arrow next to Check for Issues to open a drop-down menu. In this menu, you can specify a test file that calls the entry-point function. Select the mandelbrot_test.m
file that you used to define the input types.
You can check for issues in the generated code on the CPU or the GPU:
When you select the CPU button, GPU Coder generates code and a MEX file to run on the CPU.
When you select the GPU button, GPU Coder generates CUDA code and a MEX file to run on the GPU.
There may be MATLAB constructs in your code that cause GPU Coder to detect issues on the CPU but not on the GPU. Check for run-time issues on the CPU and then on the GPU before proceeding to the next step.
Select GPU and click the Check for Issues button. The GPU Coder app runs mandelbrot_test
and replaces calls to mandelbrot_count
with calls to the generated MEX function. In this example, GPU Coder does not detect run-time issues on the GPU.
Generate a CUDA MEX Function
In the Generate Code page, you can choose how you want GPU Coder to build the generated code. For this example, set Build type to MEX
.
Because of architectural differences between the CPU and GPU, numerical verification does not always match. In this example, the double
data type causes numeric errors between the CPU and the GPU. One reason for this mismatch is that the GPU uses floating-point multiply-add (FMAD) instructions, and the CPU does not. For more information, see Numerical Differences Between CPU and GPU.
To turn off FMAD instructions, click the More Settings button. In the left pane, click GPU Code. In the Compiler Flags box, enter --fmad=false
.
Close the settings window. Click Generate to generate the MEX file. By default, GPU Coder generates mandelbrot_count_mex
in the current directory.
To compare the generated MEX function with the original MATLAB function, see Verify Correctness of the Generated Code.