1

全部,

我有每秒调用多次的 C 函数,因为它们是 PIC18 板上控制循环的一部分。这些函数具有只需要方法范围的变量,但我想知道是否有任何开销不断分配这些变量与使用全局或至少更高范围的变量。(如果性能要求不使用方法局部变量,则考虑对结构进行类型定义以从更高的范围传递以避免使用全局变量)

这里有一些很好的主题涵盖了这个主题,但我还没有看到一个明确的答案,因为大多数人都在宣扬我同意的最佳实践,只要每微秒都没有性能提升,我就会遵循这些最佳实践。

一个线程提到使用文件范围的静态变量代替全局变量,但我不禁想知道是否有必要这样做。

大家怎么看?

4

3 回答 3

2

访问局部变量需要执行类似的操作*(SP + offset)SP堆栈指针在哪里),而访问静态变量(包括全局变量)需要执行类似*(address).

据我回忆,PIC 指令集的寻址模式非常有限。所以很有可能访问全局会更快,至少在第一次访问时是这样。如果编译器将计算的地址保存在寄存器中,则后续访问可能相同。

正如@unwind 在评论中所说,您应该查看编译器输出和配置文件以确认。如果您已经证明在程序的运行时方面是值得的,我只会牺牲清晰度/可维护性。

于 2012-02-07T15:23:43.823 回答
1

虽然我没有使用现有的每一个 PIC 编译器,但有两种风格。我使用的样式通过分析程序的调用图来静态分配所有局部变量。如果实际上执行了每个可能的调用,则本地人消耗的堆栈内存量将与静态分配所需的内存量相匹配,但有一些警告(描述 HiTech 的 PICC-18“标准”编译器的行为——其他可能会有所不同)

  1. 通过在调用者的范围内定义局部变量存储,并将指向该存储的两字节指针传递给被调用的函数来处理可变参数函数。
  2. 对于间接函数指针的每个不同签名,编译器在调用图中生成一个“伪函数”;调用该签名的函数的所有内容都调用该伪函数,并且该伪函数调用具有该签名的每个函数,该签名已获取其地址。

在这种编译器风格中,对局部变量的连续访问将与对全局变量的连续访问一样快。但是,除了显式声明为“near”的全局变量和静态变量,总长度不得超过 64-128 个字节(随 PIC 的不同型号而异),每个模块的全局变量和静态变量与局部变量分开放置,并且需要银行切换指令来访问不同银行中的东西。

我没有使用的一些编译器使用“增强指令集”选项。这个选项会吞噬 96 个字节的“near”bank(或全部,在少于 96 个字节的 PIC 上),并使用它来访问相对于 FSR2 寄存器的 96 个字节。如果它使用前 16 个或 32 个字节作为堆栈帧,这将是一个很棒的概念。使用 96 字节意味着放弃所有“近”存储,这是一个非常严重的限制。尽管如此,使用该指令集的编译器可以像访问全局变量一样快(如果不快的话)访问堆栈上的局部变量(不需要银行切换)。我真的希望 Microchip 可以选择只为堆栈帧留出 16 个字节左右,留下有用数量的“公共银行”RAM,但尽管如此,有些人对这种模式还是有好运的。

于 2012-02-07T16:28:11.167 回答
0

我想这在很大程度上取决于您使用的编译器。我不知道 PIC,但我猜一些(全部?)PIC 编译器会优化代码,以便尽可能将局部变量存储在 CPU 寄存器中。如果是这样,那么局部变量可能与全局变量一样快。

否则,如果在堆栈上分配局部变量,则全局变量的访问速度可能会更快(请参阅 Oli 的答案)。

于 2012-02-07T15:46:17.397 回答