我找了一些代碼審查和所遇到忙等待這樣:用作睡眠的空循環會被優化掉嗎?
int loop = us*32;
int x;
for(x = 0;x<loop;x++)
{
/*do nothing*/
}
我似乎記得讀這些空循環可以被優化掉。這是會發生在這裏還是可以工作?
我找了一些代碼審查和所遇到忙等待這樣:用作睡眠的空循環會被優化掉嗎?
int loop = us*32;
int x;
for(x = 0;x<loop;x++)
{
/*do nothing*/
}
我似乎記得讀這些空循環可以被優化掉。這是會發生在這裏還是可以工作?
你處於編譯器的擺佈之中。事實上,如果它很聰明,它會檢測到它是一個noop。順便說一句,尼爾·巴特沃斯有一個nice post,他在這裏也涉及到這個問題。
如果您啓用優化。 – Kevin 2012-04-24 14:43:36
感謝您的回答。這是我腦海中的事情,說這種事情可能是一個問題 – Firedragon 2012-04-24 14:46:02
不是真的,即使你不能發出內聯彙編代碼,編譯器也不會(也不能)用本地side-效果。 – 2012-04-26 08:34:51
一些編譯器,比如gcc,會檢測到它是一個空循環,特別是對於這個循環來說很悲觀,期望你把它放在那裏作爲一個延遲循環。你可以閱讀更多關於http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Non_002dbugs.html
請注意,這是編譯器特定的,
的確,我用mingw/msvc來解決這個問題,在那裏我不得不調試代碼,以便對另一個線程修改的變量進行繁忙的等待,並且循環被「優化」(在mingw情況下只用-O2)一個跳轉到自身的jmp語句(即無限循環),調試起來非常有趣。 :) – aphax 2012-10-30 22:23:24
這是非常不便攜的東西。
在一些編譯器這些可能的作品之一(但你必須檢查啓用了全面優化,空指令可以被扔掉):
for (i = 0; i < spinCount;)
++i; // yes, HERE
或:
for (i = 0; i < spinCount; ++i)
((void)0);
如果您幸運的是,你的編譯器可能會提供一個宏或者一個內部函數,這些函數將被編譯成nop
彙編指令,類似於MSVC中的__noop
。
截至上的資源,你可以簡單地添加一個單一的彙編指令(這是編譯器相關的,也可能是__asm或類似的東西)來執行...什麼都沒有,這樣的:
for (i = 0; i < spinCount; ++i)
__asm nop
或(檢查編譯器文檔):
for (i = 0; i < spinCount; ++i)
asm("nop");
編輯
如果沒有noop
指令,你可以不加彙編代碼(對不起,什麼樣的COM )你可以依賴於這樣的假設,即帶有副作用的指令不會被優化掉(或者,如由@ouah發佈的,訪問被聲明爲volatile
的變量)。
答案是肯定的,編譯器可以優化循環。
使用volatile
預選賽避免優化:
int loop = us * 32;
volatile int x;
for (x = 0; x < loop; x++)
{
/*do nothing*/
}
如果您在嵌入式編程世界閱讀你的編譯器的文檔,因爲他們通常提供延時函數等待一定的循環或微秒傳入參數。
例如,avr-gcc
在util/delay.h
以下功能:在語言標準
void _delay_us(double __us);
非常有用的評論。謝謝 – Firedragon 2012-04-25 08:45:05
閱讀關於爲什麼要使用volatile關鍵字的美麗教程:http://www.embedded.com/electronics-blogs/beginner-s-corner/4023801/Introduction-to-the-Volatile-Keyword – Prabhpreet 2014-06-16 13:57:35
沒有禁止,所以編譯器可以做到這一點,如果他們能夠。
讓我們編譯GCC 4.8,看看它做什麼
輸入代碼:
int main() {
int i;
for(i = 0; i < 16; i++)
;
}
編譯和反編譯:
gcc -c -g -std=c99 -O0 a.c
objudmp -S a.o
輸出:
a.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
int main() {
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
int i;
for(i = 0; i < 16; i++)
4: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
b: eb 04 jmp 11 <main+0x11>
d: 83 45 fc 01 addl $0x1,-0x4(%rbp)
11: 83 7d fc 0f cmpl $0xf,-0x4(%rbp)
15: 7e f6 jle d <main+0xd>
17: b8 00 00 00 00 mov $0x0,%eax
;
}
1c: 5d pop %rbp
1d: c3 retq
循環在那裏:jle
跳回。
隨着-O3
:
0000000000000000 <main>:
0: 31 c0 xor %eax,%eax
2: c3 retq
剛剛返回0,所以它完全優化掉。
對於任何編譯器都可以進行相同的分析。
也
http://stackoverflow.com/questions/3527829/is-this -a-bug-in-the-intel -c-compiler-icc/3527862#3527862 – 2012-04-24 14:42:37
yes ............ – 2012-04-24 14:42:40
'us'?如果這個代碼工作,必須是一個非常慢的CPU。 – 2012-04-24 14:45:15