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® hardware, compilers, and libraries. For information on the supported versions of the compilers and libraries, see Third-party Products. For setting up the environment variables, see Setting Up the Prerequisite Products.

The 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-2019 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';
codegen -config cfg sobelEdge -args {coder.typeof(0,[1024 1024],[1 1])}
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.

ToSpecify

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',...
'fileName','zippedsrcs');

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,...
'ignoreFileMissing',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.

IfUse
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 filesA 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 matlabroot folder tree

  • sDirFiles.zip — files in and under your build folder where you initiated code generation

  • otherFiles.zip — required files not in the matlabroot or 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.