c - 将 "falign-functions"编译器标志显式设置为特定值的动机是什么?

标签 c gcc embedded cross-compiling

我正在为一个嵌入式系统开发软件,并试图了解早期开发人员设置的一些底层细节。目标平台是定制的OpenRISC 1200处理器,在 FPGA 中合成。该软件是使用基于 GCC 的交叉编译器构建的。

在编译器标志中,我找到了这个:-falign-functions=16。构建配置中有一条评论说:

On Open RISC 1200, function alignment needs to be on a cache boundary (16 bytes). If not, performance suffer severely.

我意识到我对高速缓存的理解有点肤浅,我可能应该阅读以下内容:What Every Programmer Should Know About Memory .我还没有,但我会的。话虽如此,我有一些问题:

  1. 我知道这是为了最大限度地减少指令缓存中的缓存未命中,但为什么要通过将函数对齐设置为指令缓存行大小(即 16 字节)来实现这一点?
  2. 如果这是内存效率最高的方式,您难道不希望它成为交叉编译器中函数对齐的默认设置吗?我的意思是,对于像 x86、amd64 或 ARM 这样更常见的平台,您不需要关心函数对齐(或者我错了吗?)。

最佳答案

大多数架构都具有依赖对齐的内存访问和指令方面。

but why is that achieved by setting the function alignment to the instruction cache line size

CPU 将从内存中获取完整的缓存行(就好像内存被分成这些更大的 block 而不是字节)。因此,如果您需要的所有数据都适合一个缓存行,则只有一次提取,但如果您只有 2 个字节的数据,但一个字节是缓存行的结尾,另一个字节是下一个缓存行的开始,那么现在它必须加载两个完整的缓存行。这会浪费小型 CPU 缓存中的空间和更多的内存传输。

A quick search表示 OpenRISC 1200 使用 16 字节缓存行,因此当具体针对该缓存行时,将您拥有的任何数据的开头对齐这些 16 字节倍数有助于避免在一个函数/数据中跨越两行。

If this is the most memory efficient way, wouldn't you expect this to be the default setting for function alignment in the cross-compiler?

可能不止于此。首先,这种对齐是通过浪费“填充”内存来实现的。如果您使用了缓存行的 1 个字节来调用函数,那么另外 15 个字节将被浪费以达到 16 字节的边界。

同样在函数调用的情况下,内存无论如何都会在缓存中,向前跳转可能会离开缓存的内存,从而导致本来不需要的负载。

所以这留下了一个权衡,使用很少堆栈空间并快速返回的函数可能不会从额外对齐中获益太多,但是运行时间更长并使用更多堆栈空间的函数可能会因不“浪费”缓存空间而受益关于“上一个功能”。


通常需要对齐的另一个原因是在处理直接需要对齐(在未对齐地址上失败)或速度慢得多(加载/存储被分成几部分)或可能有其他影响(如如果没有正确对齐,则加载/存储不是原子的。

通过快速搜索,我相信 OR1200 的一般对齐要求似乎是 4 个字节,即使对于 8 字节类型也是如此。因此,在这方面,至少 4 个对齐似乎是可取的,而 8 个或 16 个可能只在前面提到的某些情况下提供好处。

我对 Open RISC 并不特别熟悉,但在后来添加的某些平台上的指令(例如 16 字节/128 位 SSE 指令)需要或受益于比默认值更大的对齐方式(我相信 AMD64 提高了默认对齐方式到 16,但后来 AVX 需要 32 字节对齐)。

关于c - 将 "falign-functions"编译器标志显式设置为特定值的动机是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59360051/

相关文章:

c 替代 signal() + alarm()

c - sha2 256 的 C 实现中的错误哈希输出

c++ - 如何使用 C 或 C++ 从 dll 中读取导出表?

c - STM32 上的加速度计事件检测

c++ - Windows 应用程序关闭

c - ANSI C 书籍链接列表章节中的错误编译示例

c - 为什么数组中的 char 在 gcc 中为 newlib 中的 isspace 给出下标警告

c++ - 如何使用 gcc/g++ 在 Linux 上为 Windows 编译?

c - 两个CPU之间棘手的队列使用

linux - 嵌入式 Linux 设备上的丰富用户界面