Main Content

Generate and Deploy Optimized Code for Wavelet Time Scattering on ARM Targets

This example shows how to generate code for wavelet time scattering with and without ARM®-specific optimizations. The example demonstrates the performance improvement on ARM targets due to the optimizations.

This example uses the code generation-only approach, where the codegen function generates code on the host computer. This example uses the packNGo function to package generated code on a host computer into a compressed zip file. You must run commands to copy the compressed zip file and other support files and build the executable program on the target hardware.

Note: This example is tested on Raspberry Pi® 4 Model B device. On the Windows platform, install plink.exe and pscp.exe for hardware and host interaction.

Create waveletScatteringProfiler Function

The waveletScatteringProfiler function reads input data and calculates the wavelet scattering features. The function is used to generate code with and without optimizations. The function profiles the waveletScattering function for 50 iterations for the same input data and saves the elapsed time of each iteration in the file profileData.txt. The generated file profileData.txt is used to compare the performance of the generated code without and with optimizations.

type waveletScatteringProfiler
function waveletScatteringProfiler(in)
% Disclaimer: This function is only intended to support "Generate and deploy 
% optimized code for wavelet time scattering  on ARM Targets" example.
% It may change or be removed in a future release.
%#codegen

%   Copyright 2022 The MathWorks, Inc.

    persistent sn;
    if isempty(sn)
        windowLength = 5e4;
        Fs = 16e3;
        IS = 0.5;
        % Instantiate wavelet scattering object.
        sn = waveletScattering(SignalLength=windowLength,SamplingFrequency=Fs,...
                               InvarianceScale=IS);
    end

    fileID = fopen('profileData.txt','w');
    formatSpec = "%f \n";

    numRuns = 50;

    for i=1:numRuns
        tic;
        % Invoke featureMatrix method on wavelet scattering object.
        S = sn.featureMatrix(in,'transform','log');
        elapsedTime = toc;
        % Write the elapse time in "profileData.txt" file.
        fprintf(fileID, formatSpec, elapsedTime);
    end

    fclose(fileID);

end

Code Generation Without Optimizations

This section demonstrates code generation and deployment of the waveletScatteringProfiler function on Raspberry Pi hardware.

Set Up Code Generation Configuration Object

Set up the code configuration object for an executable. To generate the executable, set cfg.CustomSource to the name of the main file. This example includes a custom main file (main_waveletScattering.c). The main file calls the code generated for the waveletScatteringProfiler function.

type main_waveletScattering.c
//   Copyright 2022 The MathWorks, Inc.
// Disclaimer: This function is only intended to support "Generate and deploy 
// optimized code for wavelet time scattering  on ARM Targets" example.
// It may change or be removed in a future release.

// Include Files
#include "waveletScatteringProfiler.h"
#include "waveletScatteringProfiler_terminate.h"
#include <stdlib.h>
#include <time.h>

// Function Declarations
static void argInit_50000x1_real_T(double result[50000]);

// Function Definitions
//
// Arguments    : double result[50000]
// Return Type  : void
//
static void argInit_50000x1_real_T(double result[50000]) {
    // Seed current time value in seconds.
    srand((unsigned int)time(0));
    // Loop over the array to initialize each element.
    for (int idx0 = 0; idx0 < 50000; idx0++) {
        // Set the value of the array element.
        // Change this value to the value that the application requires.
        // Assign random values between 0 and 1.
        result[idx0] = ((float)rand() / (float)(RAND_MAX));
    }
}


int main() {
    static double dv[50000];
    // Initialize function 'waveletScatteringProfiler' input arguments.
    argInit_50000x1_real_T(dv);

    // Call the entry-point 'waveletScatteringProfiler'.
    waveletScatteringProfiler(dv);

    // Terminate the application.
    // You do not need to do this more than one time.
    waveletScatteringProfiler_terminate();
    return 0;
}

//
// File trailer for main.cpp
//
// [EOF]
//

If you want to provide your own main file, generate an example main file, and use that as a template to rewrite the main file. For more information, see the GenerateExampleMain property of coder.CodeConfig (MATLAB Coder).

Create a code configuration object for an executable and generation of code only.

cfg = coder.config('exe');
cfg.CustomSource = 'main_waveletScattering.c';
cfg.GenCodeOnly = true;

Generate Code Using codegen

Generate code for the waveletScatteringProfiler function for the input size of 50000-by-1. The codegen function generates code with the folder name waveletScatteringProfiler in the current working folder on the host computer.

signalLength = 5e4;
signal = ones(signalLength,1);
codegenFolderName = 'waveletScatteringProfiler';
codegen('waveletScatteringProfiler', '-config', cfg, '-args',{signal}, '-d', codegenFolderName);
Code generation successful.

Create the Packaged Zip File Using packNGo

The packNGo function packages all relevant files in a compressed zip file.

zipFileName = [codegenFolderName, '.zip'];
bInfo = load(fullfile(codegenFolderName,'buildInfo.mat'));
packNGo(bInfo.buildInfo, {'fileName', zipFileName,'minimalHeaders', false, 'ignoreFileMissing',true});

The code is packaged in a zip file.

Build and Run Executable on Target Hardware

Run the following commands to build and run the executable on the hardware.

In the following code, specify the target device details as below:

  • hardwareName with the name or IP address of Raspberry Pi device

  • userName with your username

  • password with your password

  • codegenFolderLocationOnTarget with the location on the hardware where you want to copy the generated code

hardwareName = '<NameOfTheRaspberryPiDevice>';
userName = '<UserName>';
password = '<Password>';
codegenFolderLocationOnTarget = '<CodegenFolderLocationOnTarget>';

Use the helper function copyAndExtractZipFileInTheHardwareHelper to copy and extract zip file in the hardware target.

copyAndExtractZipFileInTheHardwareHelper(zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## Zip File copied to the hardware successfully.
## Unzipped the folder on the hardware.

Use the helper function copySupportedFilesToTheHardwareHelper to copy the support file to the target hardware. This example uses one support file:

  • waveletScatteringProfiler_rtw.mk — Makefile used to create the executable from the generated code.

supportingFiles = 'waveletScatteringProfiler_rtw.mk';
copySupportedFilesToTheHardwareHelper(supportingFiles, zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## Copied the supported files to the hardware.

Use the helper function buildAndRunExecutableOnTheHardwareHelper to build and run the executable on the hardware target.

Build and run the executable on the hardware. The executable creates the file profileData.txt, which saves the wavelet scattering function elapsed time for 50 iterations.

buildAndRunExecutableOnTheHardwareHelper(zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## Executable created successfully on the hardware.
## Started running the eecutable on the hardware...
## Ran the executable successfully on the hardware.

Extract Profiling Data Information From the Hardware

Use the helper function profileDataWithoutOptimizations to copy profileData.txt on the hardware to the MATLAB® host and read the text file data to the workspace variable profileDataWithoutOptimizations.

profileDataWithoutOptimizations = ...
    getProfilingDataFromTheHardwareHelper(zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## copied the "profileData.txt" file from hardware to the host.
## Completed writing data in "profileData.txt" to the MATLAB workspace variable.

Code Generation With Optimizations

This section demonstrates how to generate the optimal code and deployment of waveletScatteringProfiler function on Raspberry Pi hardware. This section follows steps similar to those used in the previous section. To generate optimal code, you need to make extra settings to the code configuration object.

Set Up Code Generation Configuration Object

Set up the code configuration object for an executable. To generate the executable, specify the main file in cfg.CustomSource. This example includes a custom main file (main_waveletScattering.c). The main file calls the code generated for the waveletScatteringProfiler function. Specify cfg.HardwareImplementation.ProdHWDeviceType to configure code generation for an ARM target.

cfg = coder.config('exe');
cfg.CustomSource = 'main_waveletScattering.c';
cfg.GenCodeOnly = true;
cfg.HardwareImplementation.ProdHWDeviceType = 'ARM Compatible->ARM 64-bit (LP64)';

Generate Code Using codegen

Generate code for the waveletScatteringProfiler function for the input size of 50000-by-1. The codegen function generates code with the folder name waveletScatteringProfiler in the current working folder on the host computer.

signalLength = 5e4;
signal = ones(signalLength,1);
codegenFolderName = 'waveletScatteringProfiler';
codegen('waveletScatteringProfiler', '-config', cfg, '-args',{signal}, '-d', codegenFolderName);
Code generation successful.

Create the Packaged Zip File Using packNGo

The packNGo function packages all relevant files in a compressed zip file.

zipFileName = [codegenFolderName, '.zip'];
bInfo = load(fullfile(codegenFolderName,'buildInfo.mat'));
packNGo(bInfo.buildInfo, {'fileName', zipFileName,'minimalHeaders', false, 'ignoreFileMissing',true});

The code is packaged in a zip file.

Build and Run Executable on Target Hardware

Copy the zip file and extract into the folder and remove the zip file in the hardware. Modify hardwareName, userName, and password with your Raspberry Pi device details.

hardwareName = '<NameOfTheRaspberryPiDevice>';
userName = '<UserName>';
password = '<Password>';
codegenFolderLocationOnTarget = '<CodegenFolderLocationOnTarget>';

Use the helper function copyAndExtractZipFileInTheHardwareHelper to copy and extract the zip file in the hardware target.

copyAndExtractZipFileInTheHardwareHelper(zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## Zip File copied to the hardware successfully.
## Unzipped the folder on the hardware.

Use the helper function copySupportedFilesToTheHardwareHelper to copy support file to the target hardware. This example uses one support file.

supportingFiles = 'waveletScatteringProfiler_rtw.mk';
copySupportedFilesToTheHardwareHelper(supportingFiles, zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## Copied the supported files to the hardware.

Use the helper function buildAndRunExecutableOnTheHardwareHelper to build and run the executable on the hardware target. The executable creates profileData.txt, which stores the wavelet scattering function elapsed time for 50 iterations.

buildAndRunExecutableOnTheHardwareHelper(zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## Executable created successfully on the hardware.
## Started running the eecutable on the hardware...
## Ran the executable successfully on the hardware.

Extract Profiling Data Information From the Hardware

Use the helper function getProfilingDataFromTheHardwareHelper to read the profileData.txt file from the hardware.

profileDataWithOptimizations = ...
    getProfilingDataFromTheHardwareHelper(zipFileName, hardwareName, userName, password, codegenFolderLocationOnTarget);
## copied the "profileData.txt" file from hardware to the host.
## Completed writing data in "profileData.txt" to the MATLAB workspace variable.

Compare Profiling Data With and Without Optimizations

Plot the profiling results with and without ARM-specific optimizations. You can see the significant improvement using with optimizations.

figure("Name", "Generated Code Performance Comparison")
plot(profileDataWithoutOptimizations, "-r")
hold on
plot(profileDataWithOptimizations, "-g")
legend("Without Optimizations", "With Optimizations")
hold off

title({"Generated Code Performance Comparison", "for Wavelet Time Scattering"})
xlabel("Iteration")
ylabel("Elapsed Time (Milliseconds)")

See Also

Objects

Functions

Related Examples

More About