【研发日记】Matlab/Simulink软件优化(三)——利用NaNFlag为数据处理算法降阶

文章目录

前言

背景介绍

初始算法

优化算法

分析和应用

总结


前言

见《【研发日记】Matlab/Simulink软件优化(一)------动态内存负荷压缩

见《【研发日记】Matlab/Simulink软件优化(二)------通信负载柔性均衡算法

背景介绍

在一个嵌入式软件开发项目中,需要开发一个数据处理算法,功能是求解一个动态变化数组的平均值、极值和极值位号,并且具备动态剔除个别元素(元素序列不变)的功能。示例如下:

数组:2、4、6、8、10

剔除:第1个元素、第3个元素

求均值:(4 + 8 + 10)/ 3 = 7.3

求最小值:4

求最小值位号:2

求最大值:10

求最大值位号:5

初始算法

一开始算法开发的思路非常简单,就是根据上述示例把求解过程拆分成两步,第一步构建剔除特定元素后的新数组,第二步分别求解统计结果,示例如下:

以上模型生成的代码如下:

cpp 复制代码
#include "untitled.h"
#include "untitled_private.h"

/* External outputs (root outports fed by signals with default storage) */
ExtY_untitled_T untitled_Y;

/* Real-time model */
static RT_MODEL_untitled_T untitled_M_;
RT_MODEL_untitled_T *const untitled_M = &untitled_M_;

/* Model step function */
void untitled_step(void)
{
  real_T Array_min[5];
  real_T ArrayIndex;
  int32_T b_idx;
  int32_T b_k;
  int32_T e_k;
  int32_T i;

  /* MATLAB Function: '<Root>/MATLAB Function' incorporates:
   *  Constant: '<Root>/Constant'
   */
  for (i = 0; i < 5; i++) {
    Array_min[i] = untitled_ConstP.Constant_Value[i];
  }

  Array_min[0] = 255.0;
  Array_min[2] = 255.0;
  untitled_Y.Out2 = 255.0;
  b_idx = 1;
  for (b_k = 1; b_k + 1 < 6; b_k++) {
    if (untitled_Y.Out2 > Array_min[b_k]) {
      untitled_Y.Out2 = Array_min[b_k];
      b_idx = b_k + 1;
    }
  }

  for (i = 0; i < 5; i++) {
    Array_min[i] = untitled_ConstP.Constant_Value[i];
  }

  Array_min[0] = 0.0;
  Array_min[2] = 0.0;
  untitled_Y.Out4 = 0.0;
  b_k = 1;
  for (i = 1; i + 1 < 6; i++) {
    if (untitled_Y.Out4 < Array_min[i]) {
      untitled_Y.Out4 = Array_min[i];
      b_k = i + 1;
    }
  }

  for (i = 0; i < 5; i++) {
    Array_min[i] = 0.0;
  }

  ArrayIndex = 0.0;
  for (i = 0; i < 5; i++) {
    if ((i + 1 != 1) && (i + 1 != 3)) {
      ArrayIndex++;
      Array_min[(int32_T)ArrayIndex - 1] = untitled_ConstP.Constant_Value[i];
    }
  }

  if (1.0 > ArrayIndex) {
    i = -1;
  } else {
    i = (int32_T)ArrayIndex - 1;
  }

  if ((int8_T)(i + 1) == 0) {
    ArrayIndex = 0.0;
  } else if ((int8_T)(i + 1) == 0) {
    ArrayIndex = 0.0;
  } else {
    ArrayIndex = Array_min[0];
    for (e_k = 2; e_k <= (int8_T)(i + 1); e_k++) {
      ArrayIndex += Array_min[e_k - 1];
    }
  }

  /* Outport: '<Root>/Out1' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  untitled_Y.Out1 = ArrayIndex / (real_T)(int8_T)(i + 1);

  /* Outport: '<Root>/Out3' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  untitled_Y.Out3 = b_idx;

  /* Outport: '<Root>/Out5' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  untitled_Y.Out5 = b_k;
}

/* Model initialize function */
void untitled_initialize(void)
{
  /* (no initialization code required) */
}

/* Model terminate function */
void untitled_terminate(void)
{
  /* (no terminate code required) */
}

上述代码仿真运行没有什么问题,从结果来看是符合功能需求的,示例如下:

分析上述代码会发现构建新数组时存在一些问题。如果数组中出现大于255的值,或者小于0的负数时,算法就需要重新匹配。如果数组的Size大于5,或者剔除的个数大于2,算法也需要重新匹配。这种繁复的工作,是我们不希望看到的。

优化算法

针对上述问题的分析和研究,发现Matlab官方提供了一个现成的函数功能,可用于剔除特定元素的数据统计算法,能让我们简化构建新数组的工作,也就免去了繁复匹配算法的问题,示例如下:

Tips:因为有NaN的存在,数组的数据类型如果不是double型可能会出问题。例如NaN赋给uint8型的数组是,对应元素就会变成0,再后续的求解函数中是按0对待的。

以上模型生成的代码如下:

cpp 复制代码
#include "untitled.h"
#include "untitled_private.h"

/* External outputs (root outports fed by signals with default storage) */
ExtY_untitled_T untitled_Y;

/* Real-time model */
static RT_MODEL_untitled_T untitled_M_;
RT_MODEL_untitled_T *const untitled_M = &untitled_M_;

/* Model step function */
void untitled_step(void)
{
  real_T data[5];
  real_T y;
  int32_T c_k;
  int32_T i;
  int32_T k;
  boolean_T exitg1;

  /* MATLAB Function: '<Root>/MATLAB Function' incorporates:
   *  Constant: '<Root>/Constant'
   */
  for (i = 0; i < 5; i++) {
    data[i] = untitled_ConstP.Constant_Value[i];
  }

  data[0] = (rtNaN);
  data[2] = (rtNaN);
  i = 0;
  k = 2;
  exitg1 = false;
  while ((!exitg1) && (k < 6)) {
    if (!rtIsNaN(data[k - 1])) {
      i = k;
      exitg1 = true;
    } else {
      k++;
    }
  }

  if (i == 0) {
    /* Outport: '<Root>/Out2' */
    untitled_Y.Out2 = (rtNaN);
    i = 1;
  } else {
    untitled_Y.Out2 = data[i - 1];
    for (k = i; k < 5; k++) {
      if (untitled_Y.Out2 > data[k]) {
        untitled_Y.Out2 = data[k];
        i = k + 1;
      }
    }
  }

  k = 0;
  c_k = 2;
  exitg1 = false;
  while ((!exitg1) && (c_k < 6)) {
    if (!rtIsNaN(data[c_k - 1])) {
      k = c_k;
      exitg1 = true;
    } else {
      c_k++;
    }
  }

  if (k == 0) {
    /* Outport: '<Root>/Out4' */
    untitled_Y.Out4 = (rtNaN);
    k = 1;
  } else {
    untitled_Y.Out4 = data[k - 1];
    for (c_k = k; c_k < 5; c_k++) {
      if (untitled_Y.Out4 < data[c_k]) {
        untitled_Y.Out4 = data[c_k];
        k = c_k + 1;
      }
    }
  }

  y = 0.0;
  c_k = 0;
  if (!rtIsNaN(data[1])) {
    y = data[1];
    c_k = 1;
  }

  if (!rtIsNaN(data[3])) {
    y += data[3];
    c_k++;
  }

  if (!rtIsNaN(data[4])) {
    y += data[4];
    c_k++;
  }

  /* Outport: '<Root>/Out1' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  untitled_Y.Out1 = y / (real_T)c_k;

  /* Outport: '<Root>/Out3' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  untitled_Y.Out3 = i;

  /* Outport: '<Root>/Out5' incorporates:
   *  MATLAB Function: '<Root>/MATLAB Function'
   */
  untitled_Y.Out5 = k;
}

/* Model initialize function */
void untitled_initialize(void)
{
  /* Registration code */

  /* initialize non-finites */
  rt_InitInfAndNaN(sizeof(real_T));
}

/* Model terminate function */
void untitled_terminate(void)
{
  /* (no terminate code required) */
}

Tips:从生成的C代码来看,底层逻辑的实现方法与前一种是类似的

上述代码仿真运行也没有问题,结果符合需求,示例如下:

分析上述算法的特点,不仅实现了项目中的需求,同时也利用NaNFlag为数据处理算法进行了降阶。

分析和应用

利用NaNFlag开发数据处理算法时,需要注意如下几点:

1、两种算法生成的代码,底层逻辑都一样,但是是开发复杂度和软件成熟度上差别好多,前者更适合用于逻辑探索和思维训练,后者跟适合于工程应用。

2、两种算法的开发自由度不同,可裁剪和压缩负载的空间也不同。前者可以根据实际应用裁剪出自己需要的数组大小,选取自己够用的数据类型,能更极致压缩算法对内存资源和算力资源的消耗。后者是把一部分算法设计工作交给代码生成工具去做了,开发者就没有这么大的灵活度了。前者更适用于处理器资源有限的专用嵌入式项目,后者更实用于模块化平台化开发的项目。

总结

以上就是本人在嵌入式软件开发中设计数据处理算法时,一些个人理解和分析的总结,首先介绍了它的背景情况,然后展示它的初始设计和优化设计,最后分析了利用NaNFlag开发数据处理算法的注意事项和应用场景。

后续还会分享另外几个最近总结的软件优化知识点,欢迎评论区留言、点赞、收藏和关注,这些鼓励和支持都将成文本人持续分享的动力。

另外,上述例程使用的Demo工程,可以到笔者的主页查找和下载。


版权声明:原创文章,转载和引用请注明出处和链接,侵权必究!

相关推荐
Amd79424 天前
Vue第三方库与插件实战手册
vue·echarts·d3.js·数据处理·pwa·验证·chart.js
Mr.Cssust1 个月前
燃料电池汽车践行者
燃料电池·嵌入式软件·新能源汽车·氢能·fcvc·中国汽车工程学会·中汽研
Mr.Cssust1 个月前
【文献阅读】汽车上的信息安全工程
信息安全·设计规范·网络渗透·嵌入式软件·汽车电子·智能网联汽车·嵌入式处理器
Mr.Cssust1 个月前
【文献阅读】基于模型设计的汽车软件质量属性
matlab·设计规范·兼容性·simulink·嵌入式软件·软件质量·mbd
Mr.Cssust1 个月前
【自动驾驶】针对低速无人车的线控底盘技术
人工智能·信息安全·自动驾驶·嵌入式软件·ota·功能安全·线控底盘
RestCloud1 个月前
ETLCloud中如何使用Kettle组件
etl·kettle·数据处理·数据集成·etlcloud
Mr.Cssust1 个月前
氢燃料电池汽车行业发展
电动汽车·新能源·燃料电池·嵌入式软件·行业发展·氢能·动力系统
Mr.Cssust1 个月前
【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法
异步任务·嵌入式软件·任务调度·mbd·matlab/simulink·嵌入式处理器·定时器中断
慵懒之龟1 个月前
Qt快速入门到熟练(电子相册项目(一))
开发语言·qt·嵌入式软件