这是一个有点低级别的问题.在x86程序集中有两个SSE指令:
MOVDQA xmmi, m128
和
MOVNTDQA xmmi, m128
IA-32软件开发人员手册说MOVNTDQA 中的NT代表非时间性,否则它与MOVDQA相同.
我的问题是,非时间意味着什么?
我阅读了"英特尔架构的英特尔优化指南指南".
但是,我仍然不知道何时应该使用
_mm_sfence()
_mm_lfence()
_mm_mfence()
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释在编写多线程代码时何时应该使用它们?
x86_64上的Linux glibc pthread函数是否作为弱有序内存访问的范围?(pthread_mutex_lock/unlock是我感兴趣的确切函数).
SSE2提供了一些具有弱内存排序的指令(特别是非临时存储,例如movntps).如果您正在使用这些指令并希望保证另一个线程/核心看到一个排序,那么我理解您需要一个明确的栅栏,例如,一个sfence指令.
通常,您确实希望pthread API适当地充当栅栏.但是,我怀疑x86上的正常C代码不会产生弱有序的内存访问,所以我不相信pthreads需要充当弱有序访问的栅栏.
通过glibc pthread源代码读取,最后使用"lock cmpxchgl"实现互斥,至少在无争用路径上.所以我猜我需要知道的是,该指令是否为SSE2弱有序访问的栅栏?
鉴于以下测试计划:
#include <atomic>
#include <iostream>
int64_t process_one() {
int64_t a;
//Should be atomic on my haswell
int64_t assign = 42;
a = assign;
return a;
}
int64_t process_two() {
std::atomic<int64_t> a;
int64_t assign = 42;
a = assign;
return a;
}
int main() {
auto res_one = process_one();
auto res_two = process_two();
std::cout << res_one << std::endl;
std::cout << res_two << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
编译:
g++ --std=c++17 -O3 -march=native main.cpp
Run Code Online (Sandbox Code Playgroud)
代码为这两个函数生成了以下asm:
00000000004007c0 <_Z11process_onev>:
4007c0: b8 2a 00 00 00 mov $0x2a,%eax …Run Code Online (Sandbox Code Playgroud)