c-检测目标CPU上的对齐内存需求



我目前正在尝试构建一个代码,该代码应该适用于各种机器,从手持口袋和传感器到数据中心的大型服务器。

这些体系结构之间的(许多)差异之一是对对齐内存访问的要求。

"标准"x86 CPU不需要对齐内存访问,但许多其他CPU需要它,如果不遵守规则,就会产生异常。

到目前为止,我一直在通过使用packed属性(或pragma)迫使编译器对已知有风险的特定数据访问保持谨慎来处理它。而且效果很好。

问题是,编译器过于谨慎,以至于在这个过程中损失了很多性能。

由于性能很重要,我们最好重写代码的某些部分,专门处理严格对齐的cpu。另一方面,这样的代码在支持非对齐内存访问的cpu(如x86)上会更慢,因此我们希望在需要严格对齐内存存取的cpu上只使用

现在的问题是:如何在编译时检测到目标体系结构需要严格对齐的内存访问?(或反过来)

据我所知,没有一个C实现提供任何预处理器宏来帮助您解决这个问题。由于你的代码应该在各种各样的机器上运行,我假设你可以访问各种各样的计算机进行测试,所以你可以用测试程序找出答案。然后你可以编写自己的宏,如下所示:

#if defined(__sparc__)
/* Unaligned access will crash your app on a SPARC */
#define ALIGN_ACCESS 1
#elif defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC)
/* Unaligned access is too slow on a PowerPC (maybe?) */
#define ALIGN_ACCESS 1
#elif defined(__i386__) || defined(__x86_64__) || 
      defined(_M_IX86) || defined(_M_X64)
/* x86 / x64 are fairly forgiving */
#define ALIGN_ACCESS 0
#else
#warning "Unsupported architecture"
#define ALIGN_ACCESS 1
#endif

请注意,未对齐访问的速度将取决于它所跨越的边界。例如,如果访问跨越4k页面边界,则速度会慢得多,并且可能还有其他边界会导致访问速度更慢。即使在x86上,一些未对齐的访问也不由处理器处理,而是由操作系统内核处理。这真是太慢了

也不能保证未来(或当前)的实现不会突然改变未对齐访问的性能特征。这种过去曾发生过,将来也可能发生;PowerPC 601对未对齐的访问非常宽容,但PowerPC 603e则不然。

更为复杂的是,您为进行未对齐访问而编写的代码在不同平台的实现中会有所不同。例如,在PowerPC上,如果x是32位,那么x << 32x >> 32总是0,这一事实简化了它,但在x86上就没有这样的运气了。

无论如何,为严格的内存对齐编写代码是个好主意。即使在允许未对齐访问的x86系统上,未对齐的读/写也会导致两次内存访问,并且会损失一些性能。编写适用于所有CPU架构的高效代码并不困难。要记住的简单规则是,指针必须与您正在读取或写入的对象的大小对齐。例如,如果写入DWORD,则(dest_pointer&3==0)。使用诸如"UNALIGNED_PTR"类型之类的辅助类型会导致编译器生成效率低下的代码。如果你有大量的遗留代码必须立即工作,那么使用编译器来"修复"这种情况是有意义的,但如果这是你的代码,那么从一开始就编写它,以便在所有系统上工作。

最新更新