Relocate Generated Code to Another Development Environment
If you need to relocate the generated code files to another development environment,
such as a system or an integrated development environment (IDE) that does not include
MATLAB®, you can use the packNGo
function at the command line or
the Package option in the GPU Coder™ app. The files are packaged in a compressed file that you can relocate and
unpack using a standard zip utility.
Because the code generated by using GPU Coder relies on third-party compilers, libraries to build and run the executables, the development environment that you are relocating to must also satisfy these requirements. For more information, see Installing Prerequisite Products and Setting Up the Prerequisite Products.
Note
GPU Coder requires that the 'minimalHeaders'
option of the
packNGo
command is set to false
. This setting
instructs the software to include all the header files
found on the include path in the zip file (rather than the minimal header files required
to build the code). For example,
packNGo(buildInfo,'minimalHeaders',false)
.
Package Generated Code Using the GPU Coder
This example shows how to package generated code into a zip file for relocation using the Package option in the GPU Coder app. The example uses a Sobel edge detection application to demonstrate this concept. By default, GPU Coder creates the zip file in the current working folder.
Prerequisites
NVIDIA® CUDA® enabled GPU
CUDA toolkit and drivers.
For information on the supported versions of the compilers and libraries, see Third-Party Hardware. For setting up the environment variables, see Setting Up the Prerequisite Products.
Sobel Edge Detection Entry-Point Function
In the Sobel edge detection algorithm, a 2-D spatial gradient operation on a grayscale image is performed. This operation emphasizes the high spatial frequency regions which corresponds to edges.
type sobelEdge.m
function [ magnitude ] = sobelEdge( Image ) %#codegen % Copyright 2017-2021 The MathWorks, Inc. maskX = single([-1 0 1 ; -2 0 2; -1 0 1]); maskY = single([-1 -2 -1 ; 0 0 0 ; 1 2 1]); coder.gpu.kernelfun(); resX = conv2(Image, maskX, 'same'); resY = conv2(Image, maskY, 'same'); magnitude = sqrt(resX.^2 + resY.^2); thresh = magnitude < 0.4; magnitude(thresh) = 0; end
The Sobel edge algorithm computes the horizontal gradient (resX
) and the vertical gradient (resY
) of the input image by using two orthogonal filter kernels (maskX
and maskY
). After the filtering operation, the algorithm computes the gradient magnitude and applies a threhold to find the regions of the images that are considered to be edges.
Run Sobel Edge Detection Algorithm on Test Image
The Sobel filtering algorithm operates on grayscale images. Convert the color image to an equivalent grayscale image with normalized values (0.0 for black, 1.0 for white).
im = imread('hello.jpg'); imGray = (0.2989 * double(im(:,:,1)) + 0.5870 * double(im(:,:,2)) +... 0.1140 * double(im(:,:,3)))/255; imSize = size(imGray); figure(); image(im); title('Test Image');
Write the matrix gray into the imputImage.csv
file using the writematrix
command. The Sobel edge detection application reads in this CSV file.
writematrix(reshape(imGray,1,[]),'inputImage.csv');
imOut = sobelEdge(double(imGray));
To display the edge detected image, reformat the matrix imOut
with the function repmat
so that you can pass it to the image
command.
figure();
image(repmat(imOut,[1 1 3]));
title('Edge Detected Image in MATLAB');
Create Custom Main Function for sobelEdge.m
This example uses a custom main file, main_sobel.cu
and its associdated header file main_sobel.h
. This custom main file reads the input image from the inputImage.csv
file, calls the sobelEdge
function in the generated sobelEdge.cu
file, and saves the data from the edge detected image into the outputMag.csv
file.
Package Generated Code Using the GPU Coder App
Open the GPU Coder app. On the MATLAB Toolstrip Apps tab, under Code Generation, click the GPU Coder app icon.
On the Select Source Files page, enter the name of the entry-point function sobelEdge.m
. Click Next to go to the Define Input Types page.
Specify that the input Image
is of double data type and variable size with upper bound of 1024. To specify variable size with an upper bound of 1024, select :1024
. Click Next to go to the Check for Run-Time Issues page.
Check for run-time issues. In the Check for Run-Time Issues dialog box, enter code that calls sobelEdge
with double input. For example, sobelEdge(ones(648,484))
. Click Check for Issues. To check for run-time issues, the app generates and runs a MEX function. The app does not find issues for sobelEdge
. Click Next to go to the Generate Code page.
In the Generate dialog box, set the Build Type to Executable. You can also package the code generated for Source Code, Static Library, or Dynamic Library targets. You cannot package the code generated for MEX targets. Click More Settings.
On the Custom Code tab, under Custom C Code for Generated Files, set Additional source files to main_sobel.cu
. Click Close to go to the Generate Code page.
Click Generate. Click Next to go to the Finish Workflow page. On the Finish Workflow page, click Package.
In the Package dialog box, specify the package file name and packaging type. By default, the app derives the name of the package file from the project name. The app saves the file in the current working folder. By default, the app packages the generated files as a single, flat folder. For this example, use the default values, and then click Save.
This zip file contains the CUDA C++ code and header files required for relocation. It does not contain:
Compile flags
Defines
Makefiles
Example main files, unless you configure code generation to generate and compile the example main function.
Inspect the contents of sobelEdge_pkg.zip
in your working folder to verify that it is ready for relocation to the destination system. Depending on the zip tool that you use, you can potentially open and inspect the file without unpacking it. You can now relocate the resulting zip file to the desired development environment and unpack the file.
Package Generated Code at the Command Line
To generate a CUDA executable for the sobelEdge
function, create a GPU code configuration object and run the codegen
command.
cfg = coder.gpuConfig('exe'); cfg.GenerateReport = true; cfg.CustomSource = 'main_sobel.cu'; inputArgs = {coder.typeof(0,[1024 1024],[1 1])}; codegen -config cfg sobelEdge -args inputArgs
Code generation successful: View report
To package the generated code into a zip file, load the BuildInfo
object. The BuildInfo
object contains information for compiling and linking generated code, including the list of all the source and include files and their paths.
buildInfoFile = fullfile(pwd,'codegen','exe','sobelEdge', ... 'buildInfo.mat'); load(buildInfoFile);
Create the zip file by using the packNGo
function.
packNGo(buildInfo,'packType','flat','nestedZipFiles',true,... 'minimalHeaders',false,'includeReport',false);
The packNGo
function creates the sobelEdge.zip
file in the current working folder. This zip file contains the CUDA C++ code and header files required for relocation. It does not contain:
Compile flags
Defines
Makefiles
Example main files, unless you configure code generation to generate and compile the example main function.
Inspect the contents of sobelEdge.zip
in your working folder to verify that it is ready for relocation to the destination system. Depending on the zip tool that you use, you can potentially open and inspect the file without unpacking it. You can now relocate the resulting zip file to the desired development environment and unpack the file.
Standalone Code Execution
When you execute the generated standalone executable, the output magnitudeData
is computed and written to a comma-separated file. Read this output back in MATLAB and use the image
function to visualize the edge detected image.
if ispc system('sobelEdge.exe'); else system('./sobelEdge'); end imOutGPU = reshape(readmatrix('outputMag.csv'),imSize); edgeImg = repmat(imOutGPU,[1 1 3]); figure(); image(edgeImg); title('Edge Detected Image on the GPU');
Specify packNGo Options
You can specify options for the packNGo
function.
To | Specify |
---|---|
Change the structure of the file packaging to hierarchical. | packNGo(buildInfo,'packType','hierarchical'); |
Change the structure of the file packaging to hierarchical and rename the primary zip file. | packNGo(buildInfo,'packType','hierarchical',... |
Include all header files found on the include path in the zip file (rather than the minimal header files required to build the code). For GPU Coder, this option must be set to false. | packNGo(buildInfo,'minimalHeaders',false); |
Generate warnings for parse errors and missing files. | packNGo(buildInfo,'ignoreParseError',
true,... |
For more information, see packNGo
.
Choose a Structure for the Zip File
Before you generate and package the files, decide whether you want to package the
files in a flat or hierarchical folder structure. By default, the
packNGo
function packages the files in a single, flat folder
structure. This approach is the simplest and might be the optimal choice.
If | Use |
---|---|
You are relocating files to an IDE that does not use the generated makefile, or the code is not dependent on the relative location of required static files | A single, flat folder structure |
The target development environment must maintain the folder structure of the source environment because it uses the generated makefile, or the code depends the relative location of files | A hierarchical structure |
If you use a hierarchical structure, the packNGo
function
creates two levels of zip files. There is a primary zip file, which in turn contains
the following secondary zip files:
mlrFiles.zip
— files in your
folder treematlabroot
sDirFiles.zip
— files in and under your build folder where you initiated code generationotherFiles.zip
— required files not in the
ormatlabroot
start
folder trees
Paths for the secondary zip files are relative to the root folder of the primary zip file, maintaining the source development folder structure.