Определить доступность набора инструкций SSE/SSE2 в Visual Studio
Как я могу проверить в коде, включен ли SSE/SSE2 компилятором Visual Studio?
я пытался #ifdef __SSE__
но это не сработало.
3 ответа
Из документации:
_M_IX86_FP
Расширяется до значения, указывающего, какая опция компилятора / arch использовалась:
- 0 если /arch:IA32 был использован.
- 1 если /arch:SSE был использован.
- 2 если /arch:SSE2 был использован. Это значение является значением по умолчанию, если / arch не был указан.
Я не вижу никаких упоминаний о _SSE_
,
Некоторая дополнительная информация о _M_IX86_FP
,
_M_IX86_FP определяется только для 32-битного кода. 64-битный код x86 имеет как минимум SSE2. Вы можете использовать _M_AMD64 или _M_X64, чтобы определить, является ли код 64-битным.
#ifdef __AVX2__
//AVX2
#elif defined ( __AVX__ )
//AVX
#elif (defined(_M_AMD64) || defined(_M_X64))
//SSE2 x64
#elif _M_IX86_FP == 2
//SSE2 x32
#elif _M_IX86_FP == 1
//SSE x32
#else
//nothing
#endif
Соответствующие макросы препроцессора имеют два подчеркивания на каждом конце:
#ifdef __SSE__
#ifdef __SSE2__
#ifdef __SSE3__
#ifdef __SSE4_1__
#ifdef __AVX__
...etc...
ОБНОВЛЕНИЕ: очевидно, вышеупомянутые макросы не являются автоматически предопределенными для вас при использовании Visual Studio (даже если они есть в любом другом компиляторе x86, который я когда-либо использовал), поэтому вам может потребоваться определить их самостоятельно, если вы хотите переносимости с помощью gcc, Clang, ICC и др...
Это поздний ответ, но в MSDN вы можете найти статью о __cpuid и __cpuidex. Я переделал класс в функцию, и он проверяет поддержку MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1. https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=vs-2019
[[nodiscard]] bool CheckSimdSupport() noexcept
{
std::array<int, 4> cpui;
int nIds_{};
std::bitset<32> f_1_ECX_{};
std::bitset<32> f_1_EDX_{};
std::vector<std::array<int, 4>> data_;
__cpuid(cpui.data(), 0);
nIds_ = cpui[0];
for (int i = 0; i <= 1; ++i)
{
__cpuid(cpui.data(), i);
data_.push_back(cpui);
}
if (nIds_ >= 1)
{
f_1_ECX_ = data_[1][2];
f_1_EDX_ = data_[1][3];
}
// f_1_ECX_[0] - SSE3
// f_1_ECX_[9] - SSSE3
// f_1_ECX_[19] - SSE4.1
// f_1_EDX_[23] - MMX
// f_1_EDX_[25] - SSE
// f_1_EDX_[26] - SSE2
return f_1_ECX_[0] && f_1_ECX_[9] && f_1_ECX_[19] && f_1_EDX_[23] && f_1_EDX_[25] && f_1_EDX_[26];
}