<linux kernel>plz do not use usleep(0)!
?
最近发现很多hpc 领域的MPI程序中在用usleep(0)?,比较差异。?后来问了之前做hpc?的同事?得到的答复是
一般用usleep(0)?的主要目的应该是:
CPU交出当前线程的执行权,让CPU去执行其他线程。也就是放弃当前线程的时间片,转而执行其他线程
?
我感觉很诧异。?Usleep(0)?来做这个事情?是POSIX要求的?还是一个意外的发现呢??我记得我之前都是用?sched_yield()?的啊。
于是有2个问题?
1 :usleep(0)?能不能让权,?
2?:如果可以和sched_yield?比到底谁更合适
我先man了一下usleep(0)?在linux上?,?
Usleep?不应该大于?1s?这个是确定无疑的,?但是usleep(0)?的行为?就比较诡异了。Man?上没有明确提到?看来POSIX是不要求让权的,?这在QNX?MAC?等操作系统上?明确看到
Glibc?对于?usleep(0)?是

同时linux?man?到明确写着

那usleep?究竟有没有这个效果呢?。
先来看几个奇怪的现象:

?执行shell?usleep?0?会明显的看到调用了

?难道?
usleep(0)?=?sched_yield??
?
而

?执行shell?usleep?x?(x!=0?)?会去调用naonsleep

这就比较合理了,??之前猜测?usleep??就应该是调用了?nanosleep?,
?
然后写一个?c?函数调用来看看?
会发现?无论是0??还是?!0?都是调用的

?
这就比较合理了,?看了glibc源码?也验证了确实是?封装naosleep?
那第一个问题在linux?上就变成?naosleep(0,0)?是不是会去让权了,?他和sheld_yield?的区别。?
?
在.18?之后?应该naosleep?都是基于?hrtimer的机制实现了?(
==============================================================?
do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode){hrtimer_init_sleeper(t, current);do {set_current_state(TASK_INTERRUPTIBLE);hrtimer_start_expires(&t->timer, mode);if (!hrtimer_active(&t->timer))t->task = NULL;if (likely(t->task))schedule();hrtimer_cancel(&t->timer);mode = HRTIMER_MODE_ABS;} while (t->task && !signal_pending(current));__set_current_state(TASK_RUNNING);return t->task == NULL;}?=======
补充一个?在2.6.9内核?或者可能之前的glibc实现中?usleep(0)?如果是基于?select?(0)?这样的实现??
在判断入参是0?之后会离开返回?不会调用?schelduer()的?
?
??
?
=====================================================================
?
)
?
根据nanosleep?的?syscall?,发现
?
很明显的有?schedule(),?于是可以确定?usleep(0)?如果一切顺利确实会让权,那么和sched_yield比呢?
?
于是写了一个?main?
?
?
#include <unistd.h>#include <sched.h>int main(){int j ;for(j=0; j<100000; j++)//usleep(0);sched_yield();}??
在sched_yield()?的时候?调用10万次?的耗时如下

?
?
在usleep(0)?的时候?调用10万次?的耗时如下
?

?
?
延迟简直不是一个数量级。。?太可怕了,如果用于网络?那要丢多少UDP?,?TCP要做多少次拥塞避免。
?
?
在来看一下MPI中的这个问题

?
MPI有个Yield宏,使用了?usleep(0)?,但是比较大的延迟
最后一张表的意思是,?应该尽可能的让CPU?100%,这样才算是yield。。
?
?
?
那为什么会造成usleep?如此延迟呢??
先看一下??trace的信息
Usleep?

非常可怕??因为是非主动让权?调用了?deactivate_task()有简单操作系统知识的都知道
简直就恶魔。。。

?
然而?sched_yield()

非常干净??简直perfect!?
?
?
?
我们知道?在hpc?领域?MPI?的终极目地?就是耗尽CPU?
像usleep(0)?这么高的延迟?肯定是不能用来做让权的。?而且我也不觉得?usleep(0)?可以用在任何地方?,这是一个没保证,(你知道哪天glibc改了呢)?和极其不高效的方式?。
如果你是为了耗掉一个机器周期?,那直接asm?("nop")?,如果是为了让权建议所有使用usleep(0)?(注意是0,不是其他)的地方换成?sched_yield()?;
?
?
?