【问题标题】:How does stack alignment work?堆栈对齐如何工作?
【发布时间】:2014-08-16 08:21:27
【问题描述】:

我从来没有完全理解函数中的堆栈对齐和“对齐的加载/存储”到堆栈之间的区别。

我正在阅读一些 PTX 代码并且我看到了这个:

 function()

   .local .align 16 .byte stack_memory[200];
   // This should mean the stack memory starts at an address aligned to 16 (why would this be necessary?)

   load_byte_from_stack reg, [stack_memory+1];
   // It seems reading 1 byte is always safe (why?)

   load_float32_from_stack reg, [stack_memory+8];
   // It also seems that reading 32 bit from an address aligned to 32 bit (4 bytes) is also safe (why??)

   load_two_float32_from_stack reg, [stack_memory+12];
   // This should not be right (why?)

我的问题在代码中,但重点是:

我真的不明白为什么堆栈分配应该与地址对齐,以及如果我可以从完全未对齐的地址读取 1 个字节并从仅是 4 的倍数的地址读取 float32,为什么这很重要/p>

【问题讨论】:

  • 并非所有架构都允许未对齐的访问,即使是那些这样做的架构也经常会降低性能。
  • 好吧,如果我将堆栈内存对齐到 16,我怎么能读取对齐到 4 的任何地方的浮点数?这听起来很奇怪.. 为什么一开始就将所有的东西都对齐到 16?

标签: c performance optimization memory-management cuda


【解决方案1】:

这是一个有趣的问题。让我尝试解释一下您的代码:

.local .align 16 .byte stack_memory[200]; 

问:这应该意味着堆栈内存从与 16 对齐的地址开始(为什么需要这样做?)

答:答案是因为优化和数据一致性。使缓冲区与 16B 对齐可确保缓冲区分布在最少数量的高速缓存行中。如果高速缓存行是 16B(在当前架构中通常为 64B),则缓冲区对齐将确保前 16B 存储在第一行,下一个 16B 存储在下一行,依此类推。现在,如果您想在 16B 上执行 SIMD 操作,您只需访问单个缓存行。如果没有对齐,您很可能会访问 2 个缓存行,并且如果在您访问第一行时,其他一些计算单元修改了第二行,就会发生这种情况?

load_byte_from_stack reg, [stack_memory+1];

问:似乎读取 1 个字节总是安全的(为什么?)

答:因为一个字节不能落入 2 个不同的缓存行。

load_float32_from_stack reg, [stack_memory+8]; 

问:似乎从与 32 位(4 个字节)对齐的地址读取 32 位也是安全的(为什么??)

答:同样的原因。由于对齐,您可以确定您的 4B 值不会落入 2 个连续的缓存行中。

load_two_float32_from_stack reg, [stack_memory+12];

问:这应该不对(为什么?)

答:是的,这是有问题的,主要针对具有宽松内存模型的架构。如果高速缓存行只有 16B,那么对齐到 16B 并从偏移量 12 读取 2 x 4B,将从第 1 行读取第一个 4B,从第 2 行读取下一个 4B。如果程序员不认为第二个可能会导致一些一致性问题4B在读取之前可能被别人修改(因为读取指令不能阻塞2个缓存行)。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2013-02-16
    • 2011-02-15
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2015-01-08
    • 2017-01-04
    相关资源
    最近更新 更多