我已经提到过这个网页:qazxsw poi,以下我无法理解:
pause指令给处理器一个提示,即调用线程处于“旋转等待”循环中。此外,暂停指令在不支持Intel SSE2的x86架构上使用时是无操作的,这意味着它仍然可以在不做任何事情或引发故障的情况下执行。虽然这意味着不支持英特尔SSE2的旧x86架构不会看到暂停的好处,但这也意味着您可以保留一个直接可用的代码路径。
我想知道,Linux中的lscpu会显示cpu信息,但我不知道cpu我是否支持SSE2,我怎么能自己查看?!
https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
另外,目前我使用_mm_pause或__asm volatile(“pause”:::“memory”); cpu idle将在该核心中耗尽为零,但使用nanosleep的以下代码对我来说太慢了:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 24
On-line CPU(s) list: 0-23
Thread(s) per core: 2
Core(s) per socket: 6
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 63
Model name: Intel(R) Xeon(R) CPU E5-2643 v3 @ 3.40GHz
Stepping: 2
CPU MHz: 3599.882
BogoMIPS: 6804.22
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 20480K
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23
我观察nanosleep会在我的盒子中延迟60微秒,有没有比nanosleep更快的解决方案也不会像_mm_pause()或__asm volatile(“pause”:::“memory”)那样耗尽cpu核心?
编辑:
while(1){
nanosleep();
dosomething..... ;
}
这个nanosleep花费了60微秒我在cpu上面的盒子里,我不知道它是怎么发生的?!
检查您的平台是否支持SSE2
struct timespec req={0};
req.tv_sec=0;
req.tv_nsec=100 ;
nanosleep(&req,NULL) ;
但是你不需要检查支持:gcc -march=native -dM -E - </dev/null | grep SSE
安全地解码为不能识别为pause
instruction的CPU上的NOP。 (编码基本上是pause
)。 rep nop
而不是管道中的5或100个循环暂停可能不是代码的正确性问题。
nop
不会为调度程序释放CPU,因为你提到它是为另一个目的而设计的,例如:提示微架构组件。
nanosleep,如果使用正确,应该比* 60us更精细控制(您可能需要将调度程序更改为RT)。我建议你检查你的代码,看看是否正确设置了参数等。
- 编辑 -
nanosleep函数的准确性取决于内核。短暂睡眠的行为只是在glibc中忙碌循环(参见参考资料)。如果间隔(例如,几纳秒)小于调度器节拍(由CONFIG_HZ确定,通常为250,1000等),也不可能向调度器屈服,因为调度器仅在定时器触发时上下文切换。
此外,只需将CPU空闲几纳秒,实际上不会节省电量。 CPU功率由C状态或P状态保存。 P-State使用频率缩放,而C-State关闭CPU的组件。尽管存在可以执行此类状态转换的暂停指令,但是这需要时间(在我们的范围内的延迟)这使得它变得昂贵。
参考:
_mm_pause
我认为一个简单的解决方案(比nanosleep更快)是使用多个暂停指令。
另外,请注意
重要的是要注意,暂停指令延迟的周期数可能因处理器系列而异。假设您将引入特定循环计数的延迟,则应避免使用多个暂停指令。