原子操作的成本是什么(比较和交换或原子添加/减少中的任何一种)?它消耗了多少周期?它会暂停SMP或NUMA上的其他处理器,还是会阻止内存访问? 它会在无序CPU中刷新重新排序缓冲区吗?
缓存有什么影响?
我对现代流行的CPU感兴趣:x86,x86_64,PowerPC,SPARC,Itanium。
答案 0 :(得分:52)
我查了过去几天的实际数据,一无所获。 但是,我做了一些研究,将原子操作的成本与缓存未命中的成本进行了比较。
PentiumPro之前的x86 LOCK前缀或CAS的成本(如文档中所述)是内存访问(如缓存未命中),+停止其他处理器的内存操作,+与其他处理器尝试的任何争用锁定公共汽车。但是,由于PentiumPro,对于Writeback(即可缓存)内存(应用程序处理的所有内存,除非您直接与硬件通信),而不是阻止所有内存操作,只有相关的缓存行被阻止(基于上面发布的链接)。
实际上,CAS案例可能更复杂,如this page所述,没有时间限制,但是值得信赖的工程师进行深刻的描述。
在详细介绍之前,我会说LOCKed操作会导致一次缓存未命中+与同一缓存行上其他处理器的争用,而CAS +前一次加载(除了互斥锁之外几乎总是需要)你总是CAS 0和1)可能会花费两次缓存未命中。
他解释说,单个位置上的加载+ CAS实际上可能会导致两次缓存未命中,例如Load-Linked / Store-Conditional(请参阅后者)。他的解释依赖于MESI cache coherence protocol的知识。它使用4个状态作为缓存行:M(odified),E(xclusive),S(hared),I(nvalid)(因此它称为MESI),在需要时在下面解释。解释的情况如下:
在所有情况下,已经修改数据的其他处理器可能会停止缓存行请求。
答案 1 :(得分:33)
我使用以下设置进行了一些分析:测试机器(AMD Athlon64 x2 3800+)启动,切换到长模式(中断禁用),感兴趣的指令在循环中执行,100次迭代展开,1,000次循环周期。循环体对齐到16个字节。在循环之前和之后用rdtsc指令测量时间。另外,执行了没有任何指令的虚拟循环(每个循环迭代测量2个循环,其余循环测量14个循环),结果从指令分析时间的结果中减去。
测量了以下说明:
lock cmpxchg [rsp - 8], rdx
”(比较匹配和不匹配),lock xadd [rsp - 8], rdx
”,lock bts qword ptr [rsp - 8], 1
”在所有情况下,测量的时间约为310个循环,误差约为+/- 8个循环
这是在相同(缓存)内存上重复执行的值。额外的缓存未命中,时间相当高。此外,只有两个核心中的一个处于活动状态,因此缓存是独占的,并且不需要缓存同步。
为了评估锁定指令对高速缓存未命中的成本,我在锁定指令之前添加了wbinvld
指令,并将wbinvld
加add [rsp - 8], rax
放入比较循环中。在这两种情况下,每个指令对的成本约为80,000个周期!在锁定bts的情况下,每条指令的时间差约为180个周期。
请注意,这是相互吞吐量,但由于锁定操作是序列化操作,因此延迟可能没有差异。
结论:锁定操作很重,但缓存未命中可能会更重。 另外:锁定操作不会导致缓存未命中。当高速缓存行不是专有的时候,它只会导致高速缓存同步流量。
为了启动机器,我使用了ReactOS项目中的x64版FreeLdr。这是asm源代码:
#define LOOP_COUNT 1000
#define UNROLLED_COUNT 100
PUBLIC ProfileDummy
ProfileDummy:
cli
// Get current TSC value into r8
rdtsc
mov r8, rdx
shl r8, 32
or r8, rax
mov rcx, LOOP_COUNT
jmp looper1
.align 16
looper1:
REPEAT UNROLLED_COUNT
// nothing, or add something to compare against
ENDR
dec rcx
jnz looper1
// Put new TSC minus old TSC into rax
rdtsc
shl rdx, 32
or rax, rdx
sub rax, r8
ret
PUBLIC ProfileFunction
ProfileFunction:
cli
rdtsc
mov r8, rdx
shl r8, 32
or r8, rax
mov rcx, LOOP_COUNT
jmp looper2
.align 16
looper2:
REPEAT UNROLLED_COUNT
// Put here the code you want to profile
// make sure it doesn't mess up non-volatiles or r8
lock bts qword ptr [rsp - 8], 1
ENDR
dec rcx
jnz looper2
rdtsc
shl rdx, 32
or rax, rdx
sub rax, r8
ret
答案 2 :(得分:4)
在基于总线的SMP上,原子前缀LOCK
断言(打开)总线信号LOCK#
。它将禁止总线上的其他cpus /设备使用它。
Ppro& P2书http://books.google.com/books?id=3gDmyIYvFH4C&pg=PA245&dq=lock+instruction+pentium&lr=&ei=_E61S5ehLI78zQSzrqwI&cd=1#v=onepage&q=lock%20instruction%20pentium&f=false第244-246页
锁定指令是序列化,同步操作.... / about乱序/锁定RMW / read-modify-write = atomic本身/指令确保处理器在执行锁定指令之前执行所有指令。 /关于尚未刷新写入/它强制处理器中所有发布的写入在执行下一条指令之前刷新到外部存储器。
/关于SMP /信号量处于S状态的缓存中...发出0字节日期的读取和无效事务(这是相邻CPU中缓存行的共享副本/)