Oer*_*ted 4 c++ compilation cpu-architecture compiler-optimization visual-c++
据我所知,MSVC告诉编译器使用特殊可用指令的编译选项是/arch。在 clang/linux 上,我们可以使用 -march=native 来自动检测架构和“最佳”指令集。
有没有办法用 /arch 实现同样的效果,即在当前硬件上找到此选项的最佳可用参数?
我在 MSVC 文档中找不到合适的选项。如果不存在,是否有其他解决方案(例如通过 CMake)?
MSVC 的默认值/arch:SSE2适用于 x86,并且是 x64 的隐式默认值。所有版本的 Windows 8.1 32 位或更高版本都要求安装支持 SSE2,并且所有版本的 Windows x64 都必须将 SSE2 支持作为 x64 平台定义的一部分。
对于 MSVC,只有/arch:在选择/arch:AVX或时才用于 x86/x64 /arch:AVX2。
从技术上讲,在 MSVC x86 上,您可以尝试
/arch:IA86强制使用旧版 x87 指令而不是 SSE/SSE2,但这不是推荐的解决方案或方案。这也意味着代码永远不会匹配始终使用 SSE/SSE2 的 x64 的行为。
对于 MSVC,当面向 ARM64 平台上的 Windows 时,使用
/arch:arm8.0或/arch:arm8.1确定编译器是否使用InterlockedIncrement. 在适用于 ARM64 的 Windows 11 上,整个操作系统是使用/arch:arm8.1. 如果针对 ARM64 的 Windows 10,您应该使用默认值(即/arch:arm8.0)。
MSVC 使用的另一个开关/favor用于 Intel 与 AMD 优化选择。默认值/favor:BLEND旨在成为两者之间的良好折衷。通常,只有/favor在您专门针对 Xbox ( /favor:AMD64) 或 Intel ATOM ( /favor:ATOM) 时才使用显式开关。
例如,对于 Xbox One,您使用
/favor:AMD64 /arch:AVX. 对于 Xbox Series X|S,您使用/favor:AMD64 /arch:AVX2.
对于 Clang/Linux-march=native开关,我的理解是它从主机 CPU 获取信息来确定要使用哪些设置,如果您正在构建仅打算在本地计算机上运行的代码,那么这是有意义的。这通常不是 Windows 的方法。
Clang-march与 MSVC的另一个区别/arch是,如果您使用显式内在函数,Clang确实希望您指定一个足够高的值-march以使其有效。MSVC 只是相信,如果您使用特定的内部函数,您知道自己在做什么,并且您将适当地保护代码路径。您还需要避免使用/arch:SSE2x64 编译器,因为它实际上并不支持该选项:
由于在 CMake 中没有一种很好的方法来告诉准确的目标架构,因此我使用构建变量设置为
x86、x64、ARM或ARM64对于 Ninja 场景,然后在 CMake 中按如下方式对其进行评估。如果您使用 VS MSBuild 生成器,您可以从CMAKE_GENERATOR_PLATFORM通常通过-A或在最近的 CMake 中设置的变量推断它,您可以使用CMAKE_VS_PLATFORM_NAME_DEFAULT.
if(DEFINED VCPKG_TARGET_ARCHITECTURE)
set(DIRECTX_ARCH ${VCPKG_TARGET_ARCHITECTURE})
elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Ww][Ii][Nn]32$")
set(DIRECTX_ARCH x86)
elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Xx]64$")
set(DIRECTX_ARCH x64)
elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]$")
set(DIRECTX_ARCH arm)
elseif(CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]64$")
set(DIRECTX_ARCH arm64)
elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Ww][Ii][Nn]32$")
set(DIRECTX_ARCH x86)
elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Xx]64$")
set(DIRECTX_ARCH x64)
elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Aa][Rr][Mm]$")
set(DIRECTX_ARCH arm)
elseif(CMAKE_VS_PLATFORM_NAME_DEFAULT MATCHES "^[Aa][Rr][Mm]64$")
set(DIRECTX_ARCH arm64)
endif()
...
if(NOT (${DIRECTX_ARCH} MATCHES "^arm"))
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCH_SSE2 $<$<CXX_COMPILER_ID:MSVC>:/arch:SSE2> $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-msse2>)
else()
set(ARCH_SSE2 $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-msse2>)
endif()
target_compile_options(${PROJECT_NAME} PRIVATE ${ARCH_SSE2})
endif()
Run Code Online (Sandbox Code Playgroud)