2011-07-04 46 views
3

我正在使用intel-cc編譯一些C++代碼並使用-Wall選項,它似乎是向量化了很多循環。我正在假設這對現在的表現有好處。展開循環的向量化

現在我的問題是這樣的;相反,如果for循環我已經展開,所以我們有例如

a[0] = b[0] + 1; 
a[1] = b[1] + 1; 
a[2] = b[2] + 1; 

,而不是

for(int i=0;i<3;++i) a[i] = b[i] + 1; 

可以在編譯器仍然向量化這個代碼?

此外,如果我使用相反的參考訪問元素,編譯器是否有任何希望認識到兩者是等價的?例如。

int &x, &y, &z; 
x = a[0]; y = a[1]; z = a[2]; 

然後用x,y和z代替a。

任何答案非常感謝!提前致謝。

+1

'-Wall'選項是關於生成警告,而不是向量化代碼。 – interjay

+0

是的,我知道,但它會告訴你什麼時候是矢量化的,如果你有這個選項的話。雖然也許它告訴你,無論如何? – Dan

+1

Fwiw,GNU向量化,IIRC。真正的問題是,爲什麼你要手動優化代碼,然後看看編譯器是否會設法解決你真正想做的事情?不要手動優化,直到你的分析器告訴你 – sehe

回答

1

所以我鑽研了三個簡單案例生成的程序集。下面;

for(int i=0;i<3;++i) a[i] = 1.0; // case 1 
a[0] = a[1] = a[2] = 1.0;  // case 2 
a.x = a.y = a.z = 1.0;   // case 3 

爲情況2和情況3生成的程序集是相同的。這是很好的,因爲在情況2中,編譯器給出了關於將引用複製到臨時表達式(操作符[]被覆蓋用於我的類)的「註釋」,這意味着(如果我錯了,請糾正我)編譯器正確使用返回值優化RVO)。

但是,在情況1中,編譯器輸出了一個說明,它已經將循環向量化了。大會也略有不同。特別是它包含了這個額外的代碼

 .section .rodata, "a" 
     .align 16 
     .align 16 
_2il0floatpacket.1: 
     .long 0x00000000,0x3ff00000,0x00000000,0x3ff00000 
     .type _2il0floatpacket.1,@object 
     .size _2il0floatpacket.1,16 
_2il0floatpacket.2: 
     .long 0x00000000,0x3ff00000 
     .type _2il0floatpacket.2,@object 
     .size _2il0floatpacket.2,8 

現在,我從來沒有與裝配工作,所以我不能完全肯定這是什麼額外的東西意味着,但它似乎對我暗示編譯器不能展開的循環或通過引用的訪問的情況下,量化。在編譯時也沒有提到這種效果的暗示。

如果有人可以證實這一點,那就太好了。

+0

程序集轉儲來自SIMD對齊和打包的變量(看上去像是打包了'{1.0,1.0,1.0}'),所以很明顯* did *向量化循環(它創建了一個'1.0'數組,因此它可以複製它直接使用SIMD到'a'中,所以它可能會吐出一個128位的MOVD + 64位的MOVD,從而展開循環並向量化它) – Necrolis