关于_mm_clflush与_mm_clflushout的三类技术问题咨询
1.
_mm_clflush与_mm_clflushout的核心差异 两者都是x86架构下用于刷新缓存行的编译器内置函数,分别对应CLFLUSH和CLFLUSHOUT硬件指令,核心差异集中在两点:
- 执行顺序规则不同:
_mm_clflush是强有序指令,同一核心发出的多个_mm_clflush调用会严格按照程序顺序执行,无需额外内存屏障就能保证刷新顺序;_mm_clflushout是弱有序优化版本,同一核心的多个_mm_clflushout调用之间允许乱序执行,要保证多个刷新操作的执行顺序必须手动插入sfence屏障。 - 吞吐量不同:
_mm_clflushout无需等待前序刷新操作完成即可发起新的刷新,批量刷新场景下的吞吐量比_mm_clflush高3~10倍(取决于CPU型号),更适合大内存区域的批量刷新场景。
2. 线程刷新互不重叠的内存区域时,刷新无效页操作是否线程安全
是线程安全的,原因如下:
- 缓存刷新的底层操作由CPU缓存一致性协议(如MESI)保证原子性,单个缓存行的写回、失效操作本身不会出现并发冲突。
- 各线程操作的内存区域完全不重叠,意味着不会出现多个线程同时操作同一个缓存行的情况,天然规避了竞态条件。
- 哪怕操作的是未映射的无效虚拟页,最多只会在当前触发操作的线程内抛出缺页异常,不会干扰其他线程的执行,也不会出现全局状态损坏。
3. 两条指令是否为同步指令,是否等待刷新完成后才返回
两条指令都属于同步指令,单条指令执行时会等待对应的缓存行刷新完成后才返回:
- 不管是
_mm_clflush还是_mm_clflushout,单条指令的语义都是:指令退役(retire)时,目标缓存行如果是脏行则已经完成写回内存的操作,且该缓存行在当前核心的所有缓存层级中都被标记为无效。 - 需要注意
_mm_clflushout的弱有序性只针对多条指令之间的执行顺序,不影响单条指令本身的同步特性:比如连续调用_mm_clflushout(addrA)和_mm_clflushout(addrB),可能addrB先完成刷新,但每条指令返回时都已经完成了自身对应地址的刷新操作。如果需要保证所有_mm_clflushout调用全部完成,需要额外调用sfence做全局同步。
内容的提问来源于stack exchange,提问作者user3563894
相关产品推荐
相关产品推荐

