8

我很困惑微软说 InterlockedExchange 需要内存对齐,但是英特尔文档说 LOCK 不需要内存对齐。我错过了什么,还是什么?谢谢

来自 Microsoft MSDN 库

平台 SDK:DLL、进程和线程 InterlockedExchange

Target 参数指向的变量必须在 32 位边界上对齐;否则,此函数在多处理器 x86 系统和任何非 x86 系统上的行为将无法预测。

来自英特尔软件开发人员手册;

  • LOCK 指令 使处理器的 LOCK# 信号在伴随指令的执行期间被断言(将指令变成原子指令)。在多处理器环境中,LOCK# 信号确保处理器在信号被断言时独占使用任何共享内存。

    LOCK 前缀的完整性不受内存字段对齐的影响。 对于任意未对齐的字段,会观察到内存锁定。

  • P6 和更新的处理器系列中的内存排序

    锁定指令有一个总顺序。

  • 软件控制总线锁定

    总线锁的完整性不受内存字段对齐的影响。LOCK 语义遵循更新整个操作数所需的尽可能多的总线周期。但是,建议锁定访问在其自然边界上对齐以获得更好的系统性能: • 8 位访问的任何边界(锁定或其他)。•锁定字访问的16 位边界。• 锁定双字访问的32 位边界。• 锁定四字访问的64 位边界。

4

4 回答 4

7

曾几何时,Microsoft 在 x86 以外的处理器上支持 WindowsNT,例如 MIPS、PowerPC 和 Alpha。这些处理器都需要对齐它们的互锁指令,因此微软在他们的规范中提出了要求,以确保这些原语可以移植到不同的架构。

于 2009-06-16T20:12:30.400 回答
1

即使锁定前缀不需要对齐内存,并且可能用于实现 InterlockedExchange() 的 cmpxchg 操作也不需要对齐,但如果操作系统启用了对齐检查,那么 cmpxchg 将引发对齐检查异常 (AC ) 当使用未对齐的操作数执行时。检查 cmpxchg 和类似的文档,查看保护模式异常列表。我不确定 Windows 是否启用对齐检查,但这不会让我感到惊讶。

于 2009-05-21T08:50:26.497 回答
1

嘿,回答了一些与此相关的问题,也请记住;

  1. 没有字节级别的InterlockedExchange ,但是有一个 16 位短的InterlockedExchange
  2. 您提到的文档差异可能只是一些文档疏忽。
  3. 如果你想进行字节/位级别的原子访问,有很多方法可以使用现有的内在函数 Interlocked[ And8 |Or8|Xor8]
  4. 您进行高性能锁定的任何操作(使用您讨论的机器代码)都不应未对齐操作(性能反模式
  5. xchg(具有隐式 LOCK 前缀的优化指令,由于能够缓存锁定并避免对主存储器的完全总线锁定而进行了优化)。CAN做8位联锁操作。

我几乎忘记了,从 Intel 的TBB中,他们定义了 Load/Store 8bit,不使用隐式或显式锁定(在某些情况下);

.code 
    ALIGN 4
    PUBLIC c __TBB_machine_load8
__TBB_machine_Load8:
    ; If location is on stack, compiler may have failed to align it correctly, so we do dynamic check.
    mov ecx,4[esp]
    test ecx,7
    jne load_slow
    ; Load within a cache line
    sub esp,12
    fild qword ptr [ecx]
    fistp qword ptr [esp]
    mov eax,[esp]
    mov edx,4[esp]
    add esp,12
    ret

EXTRN __TBB_machine_store8_slow:PROC
.code 
    ALIGN 4
    PUBLIC c __TBB_machine_store8
__TBB_machine_Store8:
    ; If location is on stack, compiler may have failed to align it correctly, so we do dynamic check.
    mov ecx,4[esp]
    test ecx,7
    jne __TBB_machine_store8_slow ;; tail call to tbb_misc.cpp
    fild qword ptr 8[esp]
    fistp qword ptr [ecx]
    ret
end

无论如何,希望这至少能为你解决一些问题。

于 2009-05-29T10:58:39.260 回答
-2

我不明白你的英特尔信息来自哪里。

对我来说,很明显英特尔非常关心对齐和/或跨越缓存线。

例如,在 Core-i7 处理器上,您仍然必须确保您的数据不会跨越缓存线,否则不能保证操作是原子的。

在第 3-I 卷,系统编程,对于 x86/x64 英特尔明确指出:

8.1.1 保证原子操作

Intel486 处理器(以及之后的更新处理器)保证以下基本内存操作将始终以原子方式执行:

  • 读取或写入一个字节
  • 读取或写入在 16 位边界上对齐的字
  • 读取或写入在 32 位边界上对齐的双字

Pentium 处理器(以及之后的更新处理器)保证以下额外的内存操作将始终以原子方式执行:

  • 读取或写入在 64 位边界上对齐的四字
  • 对适合 32 位数据总线的未缓存内存位置进行 16 位访问

P6 系列处理器(以及之后的更新处理器)保证以下附加内存操作将始终以原子方式执行:

  • 对适合高速缓存行的高速缓存内存进行未对齐的 16、32 和 64 位访问

Intel Core 2 Duo、Intel® Atom™、Intel Core Duo、Pentium M、Pentium 4、Intel Xeon、P6 系列、Pentium 和Intel486 处理器。Intel Core 2 Duo、Intel Atom、Intel Core Duo、Pentium M、Pentium 4、Intel Xeon 和 P6 系列处理器提供总线控制信号,允许外部存储器子系统使分离访问原子化;但是,不对齐的数据访问会严重影响处理器的性能,应该避免。

于 2011-03-03T09:39:34.407 回答