3

我目前正在尝试构建一个可以在各种机器上运行的代码,从手持口袋和传感器到数据中心的大型服务器。

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

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

到目前为止,我一直在通过使用打包属性(或 pragma)强制编译器对已知有风险的特定数据访问保持谨慎来处理它。它工作正常。

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

由于性能很重要,我们最好重写部分代码以专门用于严格对齐的 CPU。另一方面,这样的代码在支持非对齐内存访问(例如 x86)的 cpus 上会更慢,所以我们只想在需要严格对齐内存访问的 cpus 上使用

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

4

2 回答 2

5

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

于 2012-02-17T23:28:04.743 回答
5

据我所知,没有任何 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如果是 32 位,它x >> 32总是 0 x,但在 x86 上你没有这样的运气。

于 2012-02-17T23:51:40.537 回答