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 rtwdemo_differentsizereuse contains signals of different sizes and dimensions.

model='rtwdemo_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('rtwdemo_differentsizereuse','DifferentSizesBufferReuse','off');

Create a folder for the build and inspection process.

currentDir = pwd;
[~,cgDir] = rtwdemodir();

Turn off comments and build the model.

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

Build Summary

Top model targets built:

Model                       Action                       Rebuild Reason                                    
===========================================================================================================
rtwdemo_differentsizereuse  Code generated and compiled  Code generation information file does not exist.  

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

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

hfile = fullfile(cgDir,'rtwdemo_differentsizereuse_ert_rtw',...
    'rtwdemo_differentsizereuse.h');
rtwdemodbtype(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_h[3969];
  real_T z_hh[4032];
  real_T z_j[4032];
  real_T z_k[4096];
  real_T z_i[4096];
} D_Work;

The portion of rtwdemo_differentsizereuse.c is:

cfile = fullfile(cgDir,'rtwdemo_differentsizereuse_ert_rtw',...
    'rtwdemo_differentsizereuse.c');
rtwdemodbtype(cfile,'#include "rtwdemo_differentsizereuse.h"',...
    'void rtwdemo_differentsizereuse_initialize(void)',1,0);
#include "rtwdemo_differentsizereuse.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_i);
  Downsample(rtDWork.ComplextoRealImag_o2, rtDWork.z_k);
}

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_i, rtDWork.z_j);
  DeltaX(rtDWork.z_k, rtDWork.z_hh);
}

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

static void NoninplaceableSS3(void)
{
  DeltaY(rtDWork.z_j, rtDWork.z_h);
  DeltaY(rtDWork.z_hh, rtDWork.z);
}

void rtwdemo_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_h[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('rtwdemo_differentsizereuse','DifferentSizesBufferReuse','on');

Build the model.

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

Build Summary

Top model targets built:

Model                       Action                       Rebuild Reason                   
==========================================================================================
rtwdemo_differentsizereuse  Code generated and compiled  Generated code was out of date.  

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

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

rtwdemodbtype(hfile,'typedef struct {','} D_Work',1,1);
typedef struct {
  real_T z[4096];
  real_T z_h[16384];
  real_T z_o[16384];
} D_Work;

The portion of rtwdemo_differentsizereuse.c is:

cfile = fullfile(cgDir,'rtwdemo_differentsizereuse_ert_rtw',...
    'rtwdemo_differentsizereuse.c');
rtwdemodbtype(cfile,'#include "rtwdemo_differentsizereuse.h"',...
    'void rtwdemo_differentsizereuse_initialize(void)',1,0);
#include "rtwdemo_differentsizereuse.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_h, rtDWork.z);
  Downsample(rtDWork.z_o, &rtDWork.z_h[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_o[0]);
  DeltaX(&rtDWork.z_h[0], &rtDWork.z[0]);
}

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

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

void rtwdemo_differentsizereuse_step(void)
{
  int32_T i;
  for (i = 0; i < 16384; i++) {
    rtDWork.z_h[i] = rtU.ComplexData[i].re;
    rtDWork.z_o[i] = rtU.ComplexData[i].im;
  }

  NoninplaceableSS1();
  NoninplaceableSS2();
  NoninplaceableSS3();
  for (i = 0; i < 3969; i++) {
    rtY.Out1[i].re = rtDWork.z_h[i];
    rtY.Out1[i].im = rtDWork.z_o[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 and code generation report.

bdclose(model)
rtwdemoclean;
cd(currentDir)

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