协程之间的切换是一个物理线程/进程内部,用户态进行上下文之间的切换。通常协程上下文用使用双向链表链接,其个数由程序员决定。协程切换(设定为yield_thread函数)的代价+ 跳转延迟大约在20个周期左右,L2 延迟在 12个周期,L3延迟基本在50个周期,内存延迟在100ns(3GHZ,300个周期 ), 所以我们在一个进程内部引入多个协程,例如15个协程?(15 *20 周期等于内存访问 300个周期)
数据会由于三种原因执行 yield_thread函数:
1. 在取指令之后,根据指令地址预测是否产生数据L2缓存缺失,如果预测缺失,允许当前指令继续运行,但是对于内存的操作改为prefetch, 协程再切回来后重新执行该指令。
2. 在执行过程中,当得到内存地址之后,此时有更准确的预测能力,使用类似bloom filter的方式,开始做第二次预测,如果预测L2缺失,前端对yeild_thread函数再次取指,同时将内存操作变为prefetch,等到协程切回来再重新执行。
3. 若虽然预测命中,在发现L2缓存缺失的时候,前端对yeild_thread函数取指进行协程的上下文切换,同时不再等待指令返回,等效于跳转预测失败,再次切换回来时重新执行对应指令。
指令会由于二种原因执行 yield_thread函数:
1. 在取指令过程中,当得到指令地址之后,开始做第一次预测,如果预测L2缺失,前端对yeild_thread函数取指,保存上下文,等到协程切回来再重新执行。
2. 指令若预测命中,在发现L2缓存缺失的时候,前端对yeild_thread函数取指进行协程的上下文切换,同时不再等待指令返回,再次切换回来时重新执行对应指令。
注:无论数据还是指令产生的切换,当再次切回来时,默认指令/数据已经在缓存,除非发现真实缺失再做切换。
- 来自 水木社区APP v3.4.2
--
修改:MaLing FROM 42.120.75.*
FROM 42.120.75.*