Main Content

Reuse Buffers of Different Sizes and Dimensions

You can reuse buffers for matrices that have different sizes and shapes. In the Configuration Parameters dialog box, you enable this optimization by selecting Reuse buffers of different sizes and dimensions. This optimization conserves RAM and ROM usage and improves code execution speed.

Example Model

The model DifferentSizeReuse contains signals of different sizes and dimensions.

model='DifferentSizeReuse';
open_system(model);

Generate Code Without Optimization

In the Configuration Parameters dialog box, set Reuse buffers of different sizes and dimension parameter to off or in the MATLAB® Command Window, enter:

set_param('DifferentSizeReuse','DifferentSizesBufferReuse','off');

Turn off comments and build the model.

set_param('DifferentSizeReuse','GenerateComments','off');
slbuild('DifferentSizeReuse');
### Starting build procedure for: DifferentSizeReuse
### Successful completion of build procedure for: DifferentSizeReuse

Build Summary

Top model targets:

Model               Build Reason                                         Status                        Build Duration
=====================================================================================================================
DifferentSizeReuse  Information cache folder or artifacts were missing.  Code generated and compiled.  0h 0m 17.263s 

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 18.044s

View the generated code without the optimization. The D_Work structure is:

hfile = fullfile('DifferentSizeReuse_ert_rtw',...
    'DifferentSizeReuse.h');
coder.example.extractLines(hfile,'typedef struct {','} D_Work',1,1);
typedef struct {
  real_T ComplextoRealImag_o1[16384];
  real_T ComplextoRealImag_o2[16384];
  real_T z[3969];
  real_T z_n[3969];
  real_T z_j[4032];
  real_T z_m[4032];
  real_T z_g[4096];
  real_T z_e[4096];
} D_Work;

The portion of DifferentSizeReuse.c is:

cfile = fullfile('DifferentSizeReuse_ert_rtw',...
    'DifferentSizeReuse.c');
coder.example.extractLines(cfile,'#include "DifferentSizeReuse.h"',...
    'void DifferentSizeReuse_initialize(void)',1,0);
#include "DifferentSizeReuse.h"
#include "rtwtypes.h"
#include <math.h>

D_Work rtDWork;
ExternalInputs rtU;
ExternalOutputs rtY;
static RT_MODEL rtM_;
RT_MODEL *const rtM = &rtM_;
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096]);
static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032]);
static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969]);
static void NoninplaceableSS1(void);
static void NoninplaceableSS2(void);
static void NoninplaceableSS3(void);
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096])
{
  int32_T tmp;
  int32_T tmp_0;
  int32_T tmp_1;
  int32_T x;
  int32_T y;
  for (x = 0; x < 64; x++) {
    for (y = 0; y < 64; y++) {
      tmp_0 = (y + 1) << 1;
      tmp_1 = (x + 1) << 1;
      tmp = ((tmp_0 - 2) << 7) + tmp_1;
      tmp_0 = ((tmp_0 - 1) << 7) + tmp_1;
      rty_z[x + (y << 6)] = (((rtu_u[tmp - 2] + rtu_u[tmp - 1]) + rtu_u[tmp_0 -
        2]) + rtu_u[tmp_0 - 1]) / 4.0;
    }
  }
}

static void NoninplaceableSS1(void)
{
  Downsample(rtDWork.ComplextoRealImag_o1, rtDWork.z_e);
  Downsample(rtDWork.ComplextoRealImag_o2, rtDWork.z_g);
}

static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032])
{
  int32_T tmp;
  int32_T x;
  int32_T y;
  for (x = 0; x < 63; x++) {
    for (y = 0; y < 64; y++) {
      tmp = (y << 6) + x;
      rty_z[x + 63 * y] = fabs(rtu_u[tmp] - rtu_u[tmp + 1]);
    }
  }
}

static void NoninplaceableSS2(void)
{
  DeltaX(rtDWork.z_e, rtDWork.z_m);
  DeltaX(rtDWork.z_g, rtDWork.z_j);
}

static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969])
{
  int32_T i;
  for (i = 0; i < 3969; i++) {
    rty_z[i] = fabs(rtu_u[i] - rtu_u[i + 63]);
  }
}

static void NoninplaceableSS3(void)
{
  DeltaY(rtDWork.z_m, rtDWork.z_n);
  DeltaY(rtDWork.z_j, rtDWork.z);
}

void DifferentSizeReuse_step(void)
{
  int32_T i;
  for (i = 0; i < 16384; i++) {
    rtDWork.ComplextoRealImag_o1[i] = rtU.ComplexData[i].re;
    rtDWork.ComplextoRealImag_o2[i] = rtU.ComplexData[i].im;
  }

  NoninplaceableSS1();
  NoninplaceableSS2();
  NoninplaceableSS3();
  for (i = 0; i < 3969; i++) {
    rtY.Out1[i].re = rtDWork.z_n[i];
    rtY.Out1[i].im = rtDWork.z[i];
  }
}

The D_work structure contains eight global variables for holding the inputs and outputs of Downsample, DeltaX, and DeltaY. These variables have different sizes.

Generate Code with Optimization

  1. In the Configuration Parameters dialog box, verify that Signal storage reuse is selected.

  2. Set the Reuse buffers of different sizes and dimensions parameter to on or in the MATLAB Command Window, enter:

set_param('DifferentSizeReuse','DifferentSizesBufferReuse','on');

Build the model.

set_param('DifferentSizeReuse','GenerateComments','off');
slbuild(model);
### Starting build procedure for: DifferentSizeReuse
### Successful completion of build procedure for: DifferentSizeReuse

Build Summary

Top model targets:

Model               Build Reason                     Status                        Build Duration
=================================================================================================
DifferentSizeReuse  Generated code was out of date.  Code generated and compiled.  0h 0m 11.736s 

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 12.769s

View the generated code without the optimization. The D_Work structure is:

coder.example.extractLines(hfile,'typedef struct {','} D_Work',1,1);
typedef struct {
  real_T z[4096];
  real_T z_n[16384];
  real_T z_a[16384];
} D_Work;

The portion of DifferentSizeReuse.c is:

cfile = fullfile('DifferentSizeReuse_ert_rtw',...
    'DifferentSizeReuse.c');
coder.example.extractLines(cfile,'#include "DifferentSizeReuse.h"',...
    'void DifferentSizeReuse_initialize(void)',1,0);
#include "DifferentSizeReuse.h"
#include "rtwtypes.h"
#include <math.h>

D_Work rtDWork;
ExternalInputs rtU;
ExternalOutputs rtY;
static RT_MODEL rtM_;
RT_MODEL *const rtM = &rtM_;
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096]);
static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032]);
static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969]);
static void NoninplaceableSS1(void);
static void NoninplaceableSS2(void);
static void NoninplaceableSS3(void);
static void Downsample(const real_T rtu_u[16384], real_T rty_z[4096])
{
  int32_T tmp;
  int32_T tmp_0;
  int32_T tmp_1;
  int32_T x;
  int32_T y;
  for (x = 0; x < 64; x++) {
    for (y = 0; y < 64; y++) {
      tmp_0 = (y + 1) << 1;
      tmp_1 = (x + 1) << 1;
      tmp = ((tmp_0 - 2) << 7) + tmp_1;
      tmp_0 = ((tmp_0 - 1) << 7) + tmp_1;
      rty_z[x + (y << 6)] = (((rtu_u[tmp - 2] + rtu_u[tmp - 1]) + rtu_u[tmp_0 -
        2]) + rtu_u[tmp_0 - 1]) / 4.0;
    }
  }
}

static void NoninplaceableSS1(void)
{
  Downsample(rtDWork.z_n, rtDWork.z);
  Downsample(rtDWork.z_a, &rtDWork.z_n[0]);
}

static void DeltaX(const real_T rtu_u[4096], real_T rty_z[4032])
{
  int32_T tmp;
  int32_T x;
  int32_T y;
  for (x = 0; x < 63; x++) {
    for (y = 0; y < 64; y++) {
      tmp = (y << 6) + x;
      rty_z[x + 63 * y] = fabs(rtu_u[tmp] - rtu_u[tmp + 1]);
    }
  }
}

static void NoninplaceableSS2(void)
{
  DeltaX(rtDWork.z, &rtDWork.z_a[0]);
  DeltaX(&rtDWork.z_n[0], &rtDWork.z[0]);
}

static void DeltaY(const real_T rtu_u[4032], real_T rty_z[3969])
{
  int32_T i;
  for (i = 0; i < 3969; i++) {
    rty_z[i] = fabs(rtu_u[i] - rtu_u[i + 63]);
  }
}

static void NoninplaceableSS3(void)
{
  DeltaY(&rtDWork.z_a[0], &rtDWork.z_n[0]);
  DeltaY(&rtDWork.z[0], &rtDWork.z_a[0]);
}

void DifferentSizeReuse_step(void)
{
  int32_T i;
  for (i = 0; i < 16384; i++) {
    rtDWork.z_n[i] = rtU.ComplexData[i].re;
    rtDWork.z_a[i] = rtU.ComplexData[i].im;
  }

  NoninplaceableSS1();
  NoninplaceableSS2();
  NoninplaceableSS3();
  for (i = 0; i < 3969; i++) {
    rtY.Out1[i].re = rtDWork.z_n[i];
    rtY.Out1[i].im = rtDWork.z_a[i];
  }
}

The D_work structure now contains three global variables instead of eight global variables for holding the inputs and outputs of Downsample, DeltaX, and DeltaY. The generated code uses these variables to hold the differently-sized inputs and outputs.

Close the model.

bdclose(model)

Limitations

  • If you use a Reusable custom storage class to specify reuse on signals that have different sizes and shapes, you must select the Reuse buffers of different sizes and dimensions parameter. Otherwise, the model does not build.

  • The code generator does not replace a buffer with a lower priority buffer that has a smaller size.

  • The code generator does not reuse buffers that have different sizes and symbolic dimensions.

See Also

Related Topics