效率更高:大阵列或许多标量

时间:2009-09-15 23:49:28

标签: c arrays embedded

在嵌入式(PIC)环境中工作,使用c。

进行编程

我必须跟踪变量(历史记录)的1000个值并返回这些值的移动平均值。我只是想知道如果我使用数组或1000个16位变量,它在速度,ROM和RAM使用方面是否更有效。对此有一个不同的答案吗?或者我必须尝试两者并看看哪种方法效果最好?

感谢。

编辑: 嗯......我已经遇到了另一个问题。编译器将我限制为最大值为256的数组。

EDIT2:

为了澄清......代码每秒发射大约1000次。每次计算并存储history [n](或history_n)的值。每次我需要计算1000个最近历史值(包括当前值)的平均值。所以(history[1000] + history[999] + ... + history[1] + history[0]) / 1000;或其他相似之处。显然,每次我需要踢出最老的并添加最新的。

EDIT3:

我重新编写代码,现在256个数组大小不是问题。现在大约100的样本大小是合适的。

8 个答案:

答案 0 :(得分:4)

假设你需要保留历史记录,并给出256元素数组限制,这是一种管理它的方法:

int history1[256];
int history2[256];
int history3[256];
int history4[256];
int* arrays[] = {history1,history2,history3,history4}
int idx=0;
int sum = 0;
int n = 0;

int updateAverage(int newValue)
{
  int ai = (idx++)>>8;
  int* target = arrays[ai]+(idx&0xFF);

  sum -=*target;
  *target = newValue;
  sum += *target;
  n++;
  n=n<1000?n:1000;
  idx = (idx<1000)?idx:0;
  return sum/n;
}

答案 1 :(得分:2)

我不确定我是否完全理解你的问题。您是否要求为“短历史[1000]”和“简历1,历史2,...,历史1000;”生成的代码之间存在差异?

两者都应使用相似数量的RAM:每个条目将存储在单个文件寄存器中(假设您使用的是16位PIC)。计算后者平均值的代码虽然很难看,但可能需要相当多的ROM,因为它需要单独引用每个值(而不是仅仅偏移基数)。

编辑: 256元素限制的原因是因为PIC上的文件寄存器分页。只能通过偏移基址寄存器来处理更大的数组,因为您可能需要请求更改页面。

你绝对需要计算一个平均值吗?或者你可以做一个整体平均值?如果整体平均值没问题,那么使用Alphaneo答案的变体:只需保留总和,以及在两个变量中收集的值的数量,并在需要平均值时划分。

答案 2 :(得分:1)

如果使用数组,生成的代码将会小得多。我不确定这个,但我认为数组访问会使用更少的内存,因为你不必跟踪多个变量,你只需要指向一个Chunk的指针。如果您的堆栈大小是个问题,那么堆上的Array可能是最好的方法,因为C变量存储在堆栈中。

答案 3 :(得分:1)

如果您想通过将其存储在数组中来计算平均值,那么肯定比在运行时计算更昂贵。

原因-1:如果您在运行时计算它,您将继续添加例如查看以下流程

    init-0: _tempSum_ = 0
    step-1: Read current value to _currVal_
    step-2: Add current value to _tempSum_
    step-3: Check if we have required of values _num_ (eg. 1000), if not goto-1
    step-4: Calculate _avg_ = _tempSum_ / _num_ and return
    step-5: goto init-0

如果存储在1000个值的临时数组中,实际上你将完成从init-0到步骤5的所有步骤,除了你最终将使用1000值数组。

根据阵列访问时间可能会慢一点......所以要小心

答案 4 :(得分:1)

首先,您可以更改链接器文件以允许更大的部分。然后,您必须使用编译指示将历史数组放在该部分中。

其次,数组方法要好得多。要提高性能,还需要一个32位整数来保持历史数组的运行总和。

对于历史记录功能的每次触发,您将从HistoryRunningTotal中减去最旧的值并添加新的历史记录值。您还需要一个OldestHistoryIndex变量来跟踪最新值的位置(并覆盖旧历史记录)。

答案 5 :(得分:0)

如果你有1000个值的足够内存,那么为什么不静态分配内存,制作一个旋转缓冲区并移动一个指针来计算总和。 (如果运行的平均值不是你需要的)。只需继续将新值放在最旧的值上,计算1000个值的总和除以1000.实际上有两个指针,一个用于插入新值,另一个用于迭代整个缓冲区。

答案 6 :(得分:0)

编译器将数组限制为256?那太糟糕了。这给程序员带来了负担,编译器确实应该照顾它。你确定没有编译器选项,例如一个“大”的记忆模型?如果没有,请研究不同的微观和/或编译器。

或者,为了保持较小,请考虑使用小型IIR滤波器而不是大型FIR滤波器。

无论如何,要回答你原来的问题:数组是这种算法的合理选择,因为它具有合理(可维护)代码和小代码大小的好处。

答案 7 :(得分:0)

如果数组是动态分配的,那么使用静态变量会更快。如果数组是静态分配的,那么编译器应该能够将其优化为与静态变量等效的快速。尝试使用一些简单的代码并对其进行分析。