Я нашел 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 под "Properties-> C/C++ -> Code Generation", в результате чего его Not Set
для других источников, таким образом, он должен по умолчанию SSE2.
Я думал, что при этом компилятор будет создавать экземпляр шаблона один раз для каждого источника, который включает его (и не нарушать «правило одного определения», изменяя имя функции шаблона или каким-либо другим способом) и, таким образом, вызывающий программа с параметром --noavx
заставит ее работать в режиме cpus без поддержки avx.
Но результирующая программа будет иметь только одну версию функции с машинным кодом с инструкциями avx и не будет работать на более раннем процессоре.
Отключение всех других оптимизаций не решает эту проблему. Также попробовал No Enhanced Instructions - /arch:IA32
вместо Not Set
.
Как я только сейчас начинаю понимать шаблоны и тому подобное, может ли кто-нибудь указать на меня точные подробности этого поведения и что я мог бы сделать для достижения своей цели?
Мой компилятор MSVC 2013.
Дополнительная информация: файлы .obj для обоих fn_normal.cpp и fn_avx.cpp почти такой же размер в байтах. Я просмотрел сгенерированные списки сборок, и они почти одинаковы, с существенным отличием, что источник с поддержкой avx заменяет по умолчанию sse movss/mulss
на vmovss
и vmulss
соответственно.Но шагая Повсеместно кода в целях разборки Visual Studio, (Ctrl + Alt + D), подтверждает, что fnNormal()
действительно делает использование AVX специализированных инструкций.
Уверены ли вы, что настройка расширенных инструкций to'AVX 'влияет на имя mangling? Похоже, что это не так, и манипуляция имени шаблона идентична в обеих единицах перевода; так как одно из определений шаблона отбрасывается как дубликат. –
'template int RtDouble (double number)', который вы бы назвали 'RtDouble <0> (number)' и 'RtDouble <1> (number)' должен генерировать отдельные функции. –
SleuthEye
Я не думаю, что «Не задано» означает «Нет расширенного набора инструкций». – Mehrdad