cpu_relax( )-----对自选循环等待(spin-wait loops)操作的优化【转】
cpu_relax()-----对自选循环等待(spin-wait loops)操作的优化
转自:http://www.doc100.net/bugs/t/173547/index.html
在lock_timer_base()函数中看到在for循环操作中调用了cpu_relax(),本来以为是要让出CPU,调度其他进程运行,但是看代码之后发现完全不是这么回事。cpu_relax()中只有一条调用语句,调用的是rep_nop函数。rep_nop()函数如下:
static inline void rep_nop(void)
{
asm volatile("rep; nop" ::: "memory");
}
只有一条简单的汇编语句,原来在论坛里看到过这条汇编语句,不是重复执行nop指令,"rep; nop"指令会被翻译成pause指令,到底是不是这样呢?反汇编一下看看,c代码如下:
#include <stdio.h> static inline void rep_nop(void)
{
asm volatile("rep; nop" ::: "memory");
} int main(void)
{
rep_nop();
return 0;
}
文件名保存在nop.c,使用gcc编译成目标文件nop.o,命令如下:
gcc -c nop.c
使用objdump来反汇编,命令如下:
objdump -s -d nop.o
反汇编的结果如下图所示:

从图中可以看出"rep; nop"指令被翻译成pause指令,因此实际上rep_nop()函数执行了一次pause指令。关于这条指令,intel的指令手册《Instruction Set Reference, M-Z》中讲的比较详细,这里总结一下。
pause指令的作用是:
1)提升spin-wait loops(自旋循环等待)的性能。在执行一个 spin-wait loops时,Pentium4处理会遇到严重的性能损失,因为在循环退出时,处理器会检测到一个可能的内存顺序冲突。pause指令会向处理器提供一种提示,告诉处理器当前所执行的代码序列是一个spin-wait loop操作。大多数情况下,处理器会根据这个提示避开内存序列冲突,从而提高处理器的性能。正是基于此,建议在spin-wait loop中使用pause指令。
2)pause指令的另外一个功能是让Pentium4处理器在执行spin-wait loop时可以减少电源的消耗。在等待资源而执行自旋等待时,Pentium4处理器以极快的速度执行自旋等待操作时,将会消耗很多电能,但使用pause指令则可以极大地减少处理器的电源消耗。
PAUSE 指令在 Pentium4 处理器中引入,但它也是向前兼容的。在早先的 IA-32 处理器里,PAUSE 指令实际上就相当于 NOP 指令。Pentium4 处理器以一种 预延迟(pre-defined delay)的技术来实现 PAUSE 指令。这种延迟也是有限度的,并且在一些处理器上是零延迟。该指令不会改变处理器的处理器的状态。
上面还提到一个概念就是内存顺序冲突(Memory order violation)。内存顺序冲突一般是由假共享引起,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起的一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线。
参考资料:
聊聊并发(五)——原子操作的实现原理
http://www.groad.net/bbs/read.php?tid-3373.html
cpu_relax( )-----对自选循环等待(spin-wait loops)操作的优化【转】的更多相关文章
- java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring EventListener,超时处理和空循环性能优化
异步转同步 业务需求 有些接口查询反馈结果是异步返回的,无法立刻获取查询结果. 正常处理逻辑 触发异步操作,然后传递一个唯一标识. 等到异步结果返回,根据传入的唯一标识,匹配此次结果. 如何转换为同步 ...
- 采用CAS算法 实现高性能的Disruptor 完成多线程下并发、等待、先后等操作
来源:https://blog.csdn.net/tianyaleixiaowu/article/details/79787377 拓展: https://www.jianshu.com/p/d24b ...
- java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次
java后台controller中,for循环执行数据库操作,但是发现实际仅仅执行了一次,或者说提交成功了一次,并没有实际的个数循环 有可能是同一个对象导致的 可以仔细看一下下面两段代码有什么区别 p ...
- for循环中进行联网请求数据、for循环中进行异步数据操作,数据排序错乱问题解决;
for循环中进行联网请求数据,由于网络请求是异步的,第一个网络请求还没有回调,第二次第三次以及后续的网络请求又已经发出去了,有可能后续的网络请求会先回调:这时我们接收到的数据的排序就会错乱:怎么才能让 ...
- 使用增强for循环遍历集合的时候操作集合的问题?
// 遍历一个list public static void printList(List<String> list){ for (String string : list) { list ...
- 快学Scala 第三课 (定长数组,变长数组, 数组循环, 数组转换, 数组常用操作)
定长数组定义: val ar = new Array[Int](10) val arr = Array("aa", "bb") 定长数组赋值: arr(0) = ...
- 【代码学习】PYTHON 列表循环遍历及列表常见操作
一.for循环 为了更有效率的输出列表的每个数据,可以使用循环来完成 代码: A = ['xiaoWang','xiaoZhang','xiaoHua'] for tempName in A: pri ...
- 在-for 循环里面如何利用ref 操作dom
由于dom 元素是在渲染之后才能操作,所以如果想取到dom元素,要放到mounted()这个生命周期函数里面,并且还要用this.$nextTick(function () {})
- 51nod 1050 循环数组最大子段和 单调队列优化DP
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 这个呢,这个题之前 求一遍最大值 然后求一遍最小值 ...
随机推荐
- ardupilot_gazebo仿真(一)
ardupilot_gazebo仿真 标签(空格分隔): 未分类 ardupilot_gazebo仿真 官网网址 代码更新地址 Ardupilot Gazebo Plugin & Models ...
- BZOJ 1565 NOI2009 植物大战僵尸 topo+最小割(最大权闭合子图)
题目链接:https://www.luogu.org/problemnew/show/P2805(bzoj那个实在是有点小小的辣眼睛...我就把洛谷的丢出来吧...) 题意概述:给出一张有向图,这张有 ...
- Java项目启动时候报Neither the JAVA_HOME nor the JRE_HOME environment variable is defined 解决办法
今天在发布Java项目的时候又遇到 Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At leas ...
- 预处理器&预处理变量&头文件保护&条件编译
[常见的预处理功能] #include 头文件保护符 条件编译 [预处理器] 编译之前执行的一段程序,可以部分地改变我们所写的程序 举个例子:当预处理器看到#include标记时就会用指定的头文件的内 ...
- PokeCats开发者日志(八)
现在是PokeCats游戏开发的第十四天的中午,很不幸著作权申请又被打回来了. 据说是排版后代码行数还差500行,文档不足十版.我擦,原来他们会自己排版的啊. 只好从项目自带的xml里扣代 ...
- 推荐一个好的Redis GUI 客户端工具
推荐一个好的Redis GUI 客户端工具 Redis Desktop Manager
- BZOJ4347 POI2016Nim z utrudnieniem(博弈+动态规划)
由nim游戏的结论,显然等价于去掉一些数使剩下的数异或和为0. 暴力的dp比较显然,设f[i][j][k]为前i堆移走j堆(模意义下)后异或和为k的方案数.注意到总石子数量不超过1e7,按ai从小到大 ...
- 【luogu 1439 最长公共子序列】
题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...
- 【BZOJ 1592】[Usaco2008 Feb]Making the Grade 路面修整 dp优化之转移变状态
我们感性可证离散(不离散没法做),于是我们就有了状态转移的思路(我们只考虑单不减另一个同理),f[i][j]到了第i块高度为j的最小话费,于是我们就可以发现f[i][j]=Min(f[i-1][k]) ...
- [fzu 2273]判断两个三角形的位置关系
首先判断是否相交,就是枚举3*3对边的相交关系. 如果不相交,判断包含还是相离,就是判断点在三角形内还是三角形外.两边各判断一次. //http://acm.fzu.edu.cn/problem.ph ...