Main Content

Accelerate Code Using fiaccel

Speeding Up Fixed-Point Execution with fiaccel

You can convert fixed-point MATLAB® code to MEX functions using fiaccel. The generated MEX functions contain optimizations to automatically accelerate fixed-point algorithms to compiled C/C++ code speed in MATLAB. The fiaccel function can greatly increase the execution speed of your algorithms.

Running fiaccel

The basic command is:

fiaccel M_fcn

By default, fiaccel performs the following actions:

  • Searches for the function M_fcn stored in the file M_fcn.m as specified in Compile Path Search Order.

  • Compiles M_fcn to MEX code.

  • If there are no errors or warnings, generates a platform-specific MEX file in the current folder, using the naming conventions described in File Naming Conventions.

  • If there are errors, does not generate a MEX file, but produces an error report in a default output folder, as described in Generated Files and Locations.

  • If there are warnings, but no errors, generates a platform-specific MEX file in the current folder, but does report the warnings.

You can modify this default behavior by specifying one or more compiler options with fiaccel, separated by spaces on the command line.

Generated Files and Locations

fiaccel generates files in the following locations:

Generates:In:

Platform-specific MEX files

Current folder

code generation reports

(if errors or warnings occur during compilation)

Default output folder:

fiaccel/mex/M_fcn_name/html

You can change the name and location of generated files by using the options -o and -d when you run fiaccel.

In this example, you will use the fiaccel function to compile different parts of a simple algorithm. By comparing the run times of the two cases, you will see the benefits and best use of the fiaccel function.

Compare Run Times When Accelerating Different Algorithm Parts

This example shows how to use the fiaccel function to compile different parts of a simple algorithm.

The algorithm used throughout this example replicates the functionality of the MATLAB sum function, which sums the columns of a matrix.

type fi_matrix_column_sum.m
function B = fi_matrix_column_sum(A)
% Sum the columns of matrix A.

% Copyright 2008-2023 The MathWorks, Inc.
%#codegen
    [m,n] = size(A);
    w = get(A,'WordLength') + ceil(log2(m));
    f = get(A,'FractionLength');
    B = fi(zeros(1,n),true,w,f,fimath(A));
    for j = 1:n
        for i = 1:m
            B(j) = B(j) + A(i,j);
        end
    end

Trial 1: Best Performance

The best way to speed up the execution of the algorithm is to compile the entire algorithm using the fiaccel function. To evaluate the performance improvement provided by the fiaccel function when the entire algorithm is compiled, run the following code.

The first portion of code executes the algorithm using only MATLAB functions.

fipref('NumericTypeDisplay','short');
A = fi(randn(1000,10));
tic
B = fi_matrix_column_sum(A);
t_matrix_column_sum_m = toc
t_matrix_column_sum_m = 2.6281

The second portion of the code compiles the entire algorithm using the fiaccel function. The MATLAB tic and toc functions keep track of the run times for each method of execution.

fiaccel fi_matrix_column_sum -args {A}
tic
B = fi_matrix_column_sum_mex(A);
t_matrix_column_sum_mex = toc
t_matrix_column_sum_mex = 0.1486

Trial 2: Worst Performance

Compiling only the smallest unit of computation using the fiaccel function leads to much slower execution. In some cases, the overhead that results from calling the mex function inside a nested loop can cause even slower execution than using MATLAB functions alone. To evaluate the performance of the mex function when only the smallest unit of computation is compiled, run the following code.

The first portion of code executes the algorithm using only MATLAB functions.

tic
[m,n] = size(A);
w = get(A,'WordLength') + ceil(log2(m));
f = get(A,'FractionLength');
B = fi(zeros(1,n),true,w,f);
for j = 1:n
    for i = 1:m
        B(j) = fi_scalar_sum(B(j),A(i,j));
        % B(j) = B(j) + A(i,j);
    end
end
t_scalar_sum_m = toc
t_scalar_sum_m = 11.6898

The second portion of the code compiles the smallest unit of computation with the fiaccel function, leaving the rest of the computations to MATLAB.

fiaccel fi_scalar_sum -args {B(1),A(1,1)}
tic
[m,n] = size(A);
w = get(A,'WordLength') + ceil(log2(m));
f = get(A,'FractionLength');
B = fi(zeros(1,n),true,w,f);
for j = 1:n
    for i = 1:m
        B(j) = fi_scalar_sum_mex(B(j),A(i,j));
        % B(j) = B(j) + A(i,j);
    end
end
t_scalar_sum_mex = toc
t_scalar_sum_mex = 5.4765

Ratio of Times

Compare the results of Trial 1 and Trial 2. Your computer may record different times, but the ratios should be approximately the same. There is a significant difference in ratios between the trial where the entire algorithm was compiled using fiaccel (t_matrix_column_sum_mex.m) and where only the scalar sum was compiled (t_scalar_sum_mex.m). Even the file with no fiaccel compilation (t_matrix_column_sum_m) did better than when only the smallest unit of computation was compiled using fiaccel (t_scalar_sum_mex).

t_scalar_sum_mex/t_matrix_column_sum_mex
ans = 36.8480
t_scalar_sum_mex/t_matrix_column_sum_m
ans = 2.0838
t_matrix_column_sum_m/t_matrix_column_sum_mex
ans = 17.6830
t_scalar_sum_m/t_scalar_sum_mex
ans = 2.1346

Trial 1: Best Performance

The best way to speed up the execution of the algorithm is to compile the entire algorithm using the fiaccel function. To evaluate the performance improvement provided by the fiaccel function when the entire algorithm is compiled, run the following code.

The first portion of code executes the algorithm using only MATLAB functions. The second portion of the code compiles the entire algorithm using the fiaccel function. The MATLAB tic and toc functions keep track of the run times for each method of execution.

% MATLAB
fipref('NumericTypeDisplay','short');
A = fi(randn(1000,10));
tic
B = fi_matrix_column_sum(A)
t_matrix_column_sum_m = toc

% fiaccel
fiaccel fi_matrix_column_sum -args {A}
tic
B = fi_matrix_column_sum_mex(A);
t_matrix_column_sum_mex = toc

Trial 2: Worst Performance

Compiling only the smallest unit of computation using the fiaccel function leads to much slower execution. In some cases, the overhead that results from calling the mex function inside a nested loop can cause even slower execution than using MATLAB functions alone. To evaluate the performance of the mex function when only the smallest unit of computation is compiled, run the following code.

The first portion of code executes the algorithm using only MATLAB functions. The second portion of the code compiles the smallest unit of computation with the fiaccel function, leaving the rest of the computations to MATLAB.

% MATLAB
tic
[m,n] = size(A);
w = get(A,'WordLength') + ceil(log2(m));
f = get(A,'FractionLength');
B = fi(zeros(1,n),true,w,f);
for j = 1:n
    for i = 1:m
        B(j) = fi_scalar_sum(B(j),A(i,j));
        % B(j) = B(j) + A(i,j);
    end
end
t_scalar_sum_m = toc

% fiaccel
fiaccel fi_scalar_sum -args {B(1),A(1,1)}
tic
[m,n] = size(A);
w = get(A,'WordLength') + ceil(log2(m));
f = get(A,'FractionLength');
B = fi(zeros(1,n),true,w,f);
for j = 1:n
    for i = 1:m
        B(j) = fi_scalar_sum_mex(B(j),A(i,j));
        % B(j) = B(j) + A(i,j);
    end
end
t_scalar_sum_mex = toc

Ratio of Times

A comparison of Trial 1 and Trial 2 appears in the following table. Your computer may record different times than the ones the table shows, but the ratios should be approximately the same. There is an extreme difference in ratios between the trial where the entire algorithm was compiled using fiaccel (t_matrix_column_sum_mex.m) and where only the scalar sum was compiled (t_scalar_sum_mex.m). Even the file with no fiaccel compilation (t_matrix_column_sum_m) did better than when only the smallest unit of computation was compiled using fiaccel (t_scalar_sum_mex).

X (Overall Performance Rank)TimeX/BestX_m/X_mex
Trial 1: Best Performance
t_matrix_column_sum_m (2) 1.9975984.4917 84.4917
t_matrix_column_sum_mex (1)0.02364241
Trial 2: Worst Performance
t_scalar_sum_m (4)10.2067 431.71 2.08017
t_scalar_sum_mex (3)4.90664 207.536

Data Type Override Using fiaccel

To turn data type override on, type the following command at the MATLAB prompt after running the reset(fipref) command:

fipref('DataTypeOverride','TrueDoubles')

This command tells Fixed-Point Designer™ software to create all fi objects with type fi double. When you compile the code using the fiaccel command, the resulting MEX-function uses floating-point data.

Specifying Default fimath Values for MEX Functions

MEX functions generated with fiaccel use the MATLAB default global fimath. The MATLAB factory default global fimath has the following properties:

RoundingMethod: Nearest
OverflowAction: Saturate
ProductMode: FullPrecision
SumMode: FullPrecision

When running MEX functions that depend on the MATLAB default fimath value, do not change this value during your MATLAB session. Otherwise, MATLAB generates a warning, alerting you to a mismatch between the compile-time and run-time fimath values. For example, create the following MATLAB function:

function y = test %#codegen 
y = fi(0); 
The function test constructs a fi object without explicitly specifying a fimath object. Therefore, test relies on the default fimath object in effect at compile time.

Generate the MEX function test_mex to use the factory setting of the MATLAB default fimath.

resetglobalfimath;
fiaccel test 
fiaccel generates a MEX function, test_mex, in the current folder.

Run test_mex.

test_mex   
ans =        
  0            
       DataTypeMode: Fixed-point: binary point scaling            
       Signedness: Signed            
       WordLength: 16        
       FractionLength: 15

Modify the MATLAB default fimath value so it no longer matches the setting used at compile time.

F = fimath('RoundingMethod','Floor');
globalfimath(F); 

Clear the MEX function from memory and rerun it.

clear test_mex 
test_mex
The mismatch is detected and MATLAB generates a warning.
testglobalfimath_mex 
Warning: This function was generated with a 
different default fimath than the current default.
ans =        
   0            
      DataTypeMode: Fixed-point: binary point scaling
      Signedness: Signed             
      WordLength: 16         
      FractionLength: 15
To avoid this issue, separate the fimath properties from your algorithm by using types tables. For more information, see Separate Data Type Definitions from Algorithm.