Clear Filters
Clear Filters

code generation of a function with multiple sub-functions

7 views (last 30 days)
Hi All,
I tried to apply code generation for a function which includes multiple sub-functions inside. The generated C code expands those sub-functions. My purpose is to perserve those sub-functions after code generation to maintain the code architecture the same with that of matlab code.
Matlab Code
function [add_out, mul_out] = addmul(a, b)
%#codegen
add_out = add_func(a,b);
mul_out = mul_func(a,b);
end
function out = add_func(a, b)
out = a + b;
end
function out = mul_func(a,b)
out = a .* b;
end
Generated C code
void addmul(const double a_data[], const int a_size[2], const double b_data[],
const int b_size[2], double add_out_data[], int add_out_size[2],
double mul_out_data[], int mul_out_size[2])
{
int i;
int loop_ub_tmp;
(void)b_size;
add_out_size[0] = 1;
add_out_size[1] = a_size[1];
loop_ub_tmp = a_size[0] * a_size[1];
for (i = 0; i < loop_ub_tmp; i++) {
add_out_data[i] = (a_data[i] + b_data[i]);
}
mul_out_size[0] = 1;
mul_out_size[1] = a_size[1];
for (i = 0; i < loop_ub_tmp; i++) {
mul_out_data[i] = a_data[i] * b_data[i];
}
}
Expected Generated C code
void add_func(double a, double b, double *out) {
*out = a + b;
}
void mul_func(double a, double b, double *out) {
*out = a * b;
}
void addmul(const double a_data[], const int a_size[2], const double b_data[],
const int b_size[2], double add_out_data[], int add_out_size[2],
double mul_out_data[], int mul_out_size[2])
{
int i;
int loop_ub_tmp;
(void)b_size;
add_out_size[0] = 1;
add_out_size[1] = a_size[1];
loop_ub_tmp = a_size[0] * a_size[1];
for (i = 0; i < loop_ub_tmp; i++) {
add_func(a_data[i], b_data[i], (double*)(add_out_data + i));
}
mul_out_size[0] = 1;
mul_out_size[1] = a_size[1];
for (i = 0; i < loop_ub_tmp; i++) {
mul_func(a_data[i], b_data[i], (double*)(add_out_data + i));
}
}

Answers (1)

Anil
Anil on 28 Sep 2022
Hi Kun-Lin,
It is my understanding that you would like to apply code generation for a function which includes multiple sub-functions inside and prevent the inlining/expanding of sub functions. There are a couple of ways to go about this. One option is to use InlineBetweenUserFunctions options of coder config. For example, for the example provided in the question,
>> cfg = code.config('lib');
>> cfg.InlineBetweenUserFunctions = "Never";
>> codegen addmul -args {coder.typeof(1, [1 100], [0 1]), coder.typeof(1, [1 100], [0 1])} -nargout 2 -config cfg
This generates the following code:
void addmul(const double a_data[], const int a_size[2], const double b_data[],
const int b_size[2], double add_out_data[], int add_out_size[2],
double mul_out_data[], int mul_out_size[2])
{
add_func(a_data, a_size, b_data, b_size, add_out_data, add_out_size);
mul_func(a_data, a_size, b_data, b_size, mul_out_data, mul_out_size);
}
Alternatively, one can use coder.inline(‘never’) option to functions that you do not require to be inlined.
So, the example code will be as follows:
function [add_out, mul_out] = addmul(a, b)
%#codegen
add_out = add_func(a,b);
mul_out = mul_func(a,b);
end
function out = add_func(a, b)
coder.inline('never');
out = a + b;
end
function out = mul_func(a,b)
coder.inline('never');
out = a .* b;
end
However, the thing to note here is that the generated code is still not equivalent to the expected example you provided. The for loop to perform the operations are inside the functions. To generate code closer to the one you expect one must modify the code to have the for loop outside the function calls as follows,
function [add_out, mul_out] = addmul(a, b)
%#codegen
add_out = coder.nullcopy(zeros(size(a), 'like', a));
mul_out = coder.nullcopy(zeros(size(a), 'like', a));
for i = 1:numel(a)
add_out(i) = add_func(a(i),b(i));
end
for i = 1:numel(a)
mul_out(i) = mul_func(a(i),b(i));
end
end
function out = add_func(a, b)
coder.inline('never');
out = a + b;
end
function out = mul_func(a,b)
coder.inline('never');
out = a .* b;
end
Here the generated code is as follows,
void addmul(const double a_data[], const int a_size[2], const double b_data[],
const int b_size[2], double add_out_data[], int add_out_size[2],
double mul_out_data[], int mul_out_size[2])
{
int b_i;
int i;
(void)b_size;
add_out_size[0] = 1;
add_out_size[1] = a_size[1];
mul_out_size[0] = 1;
mul_out_size[1] = a_size[1];
i = a_size[1];
for (b_i = 0; b_i < i; b_i++) {
add_out_data[b_i] = add_func(a_data[b_i], b_data[b_i]);
}
i = a_size[1];
for (b_i = 0; b_i < i; b_i++) {
mul_out_data[b_i] = mul_func(a_data[b_i], b_data[b_i]);
}
}

Categories

Find more on Generating Code in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!