我發現a question somewhat interesting,並繼續嘗試回答它。作者想要編譯一個源文件(依賴於模板庫)和AVX優化,而其餘的項目不包含這些。如何有條件地爲模板標頭設置編譯器優化
所以,看看會發生什麼,我創建了一個測試項目是這樣的:
的main.cpp
#include <iostream>
#include <string>
#include "fn_normal.h"
#include "fn_avx.h"
int main(int argc, char* argv[])
{
int number = 10; // this will come from input, but let's keep it simple for now
int result;
if (std::string(argv[argc - 1]) == "--noavx")
result = FnNormal(number);
else
{
std::cout << "AVX selected\n";
result = FnAVX(number);
}
std::cout << "Double of " << number << " is " << result << std::endl;
return 0;
}
文件fn_normal.h和fn_avx.h分別包含函數FnNormal()
和FnAVX()
的聲明,其定義如下:
fn_normal.cpp
#include "fn_normal.h"
#include "double.h"
int FnNormal(int num)
{
return RtDouble(num);
}
fn_avx.cpp
#include "fn_avx.h"
#include "double.h"
int FnAVX(int num)
{
return RtDouble(num);
}
而這裏的模板函數的定義:
double.h
template<typename T>
int RtDouble(T number)
{
// Side effect: generates avx instructions
const int N = 1000;
float a[N], b[N];
for (int n = 0; n < N; ++n)
{
a[n] = b[n] * b[n] * b[n];
}
return number * 2;
}
最後,我設置Enhanced Instruction Set
到AVX
爲下的文件fn_avx.cpp「屬性 - > C/C++ - >代碼生成」,把它留給Not Set
爲其他來源,因此應默認SSE2。
我認爲通過這樣做,編譯器將爲包含它的每個源實例化一次模板(並避免通過改變模板函數名稱或其他方式來違反「一維定義規則」),從而調用帶--noavx
參數的程序會使其在沒有avx支持的情況下在cpus中正常運行。
但是生成的程序實際上只有一個機器代碼版本的函數,包含avx指令,並且在較老的cpus上會失敗。
禁用所有其他優化不能解決此問題。也試過No Enhanced Instructions - /arch:IA32
而不是Not Set
。
因爲我剛剛開始瞭解模板等,有人可以指向我此行爲的具體細節以及我實際上可以做些什麼來實現我的目標?
我的編譯器是MSVC 2013年
附加信息:兩個fn_normal.cpp和fn_avx.cpp幾乎字節大小相同的.obj文件。我查看了生成的彙編列表,它們幾乎相同,重要的區別在於啓用avx的源分別替換默認sse的movss/mulss
和vmovss
和vmulss
。但步進throught在Visual Studio中的反彙編視圖代碼(按Ctrl + Alt鍵+d),證實確實fnNormal()
利用的AVX專用指令。
你確定「增強指令集設置爲'AVX'」設置會影響名稱修改嗎?聽起來好像沒有,模板的名字在兩個翻譯單元中都是相同的;因爲這樣的模板定義之一被丟棄爲重複。 – 2015-03-31 23:48:40
'template int RtDouble(double number)'你可以打電話給'RtDouble <0>(number)'和'RtDouble <1>(number)'應該生成單獨的函數。 –
SleuthEye
2015-04-01 00:11:43
我不認爲「未設置」表示「沒有增強的指令集」。 – Mehrdad 2015-04-01 00:15:59