我目前正在尝试构建一个适用于各种机器的代码,从手持式口袋和传感器到数据中心的大型服务器。
这些体系结构之间的(许多)差异之一是对齐内存访问的要求。
"标准"不需要对齐的内存访问。 x86 CPU,但许多其他CPU需要它并在不遵守规则时产生异常。
到目前为止,我一直在使用packed属性(或pragma)强制编译器对已知存在风险的特定数据访问保持谨慎。它工作正常。
问题是,编译器非常谨慎,以至于在此过程中会丢失大量性能。
由于性能很重要,我们最好重写代码的某些部分以专门处理严格对齐的cpus。另一方面,这样的代码在cpus上会更慢,它支持未对齐的内存访问(例如x86),因此我们希望在cpus上仅使用 ,这需要严格对齐的内存访问。
现在的问题是: 如何在编译时检测目标体系结构是否需要严格对齐的内存访问? (或反过来说)
答案 0 :(得分:5)
编写代码以进行严格的内存对齐无论如何都是个好主意。即使在允许未对齐访问的x86系统上,您的未对齐读/写也会导致两次内存访问,并且某些性能将会丢失。编写适用于所有CPU架构的高效代码并不困难。要记住的简单规则是指针必须与您正在读取或写入的对象的大小对齐。例如如果写一个DWORD,那么(dest_pointer&amp; 3 == 0)。使用诸如“UNALIGNED_PTR”类型之类的拐杖将导致编译器生成低效代码。如果你有大量必须立即工作的遗留代码,那么使用编译器“修复”这种情况是有意义的,但是如果它是你的代码,那么从一开始就把它写在所有系统上。< / p>
答案 1 :(得分: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上,一些未对齐的访问也不由处理器处理,而是由OS内核处理。那是非常慢。
也不能保证未来(或当前)实现不会突然改变未对齐访问的性能特征。这个过去发生过,可能会在将来发生; PowerPC 601对非对齐访问非常宽容,但PowerPC 603e却没有。
进一步复杂化的事实是,您编写的用于进行未对齐访问的代码在跨平台的实现方面会有所不同。例如,在PowerPC上,x << 32
和x >> 32
总是0,如果x
是32位,那么简化了这一事实,但在x86上你没有这样的运气。