c++ 相当于-march=native for msvc

f4t66c6m  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(141)

据我所知,MSVC的编译选项告诉编译器使用特殊的可用指令是/arch。在clang/Linux上,我们可以使用-march=native来自动检测体系结构和“最佳”指令集。
有没有一种方法可以用/arch实现同样的事情,即在当前硬件上找到这个选项的最佳参数?
我在MSVC文档中找不到合适的选项。如果不存在,是否有其他解决方案(例如通过CMake)?

7dl7o3gd

7dl7o3gd1#

MSVC的默认值是x86的/arch:SSE2,是x64的隐式默认值。所有版本的Windows 8.1 32位或更高版本都要求安装支持SSE 2,所有版本的Windows x64都必须将SSE 2支持作为x64平台定义的一部分。
对于MSVC,只有当您选择/arch:AVX/arch:AVX2时,才会将/arch:用于x86/x64。
从技术上讲,在MSVC x86上,您可以使用/arch:IA86来尝试强制使用遗留x87指令而不是SSE/SSE 2,但这不是推荐的解决方案或场景。这也意味着代码永远不会匹配始终使用SSE/SSE 2的x64的行为。
对于MSVC,当针对ARM 64平台上的Windows时,/arch:arm8.0/arch:arm8.1的使用决定了编译器是否使用InterlockedIncrement的CPU指令。在Windows 11 for ARM 64上,整个操作系统都是使用/arch:arm8.1构建的。如果针对Windows 10 for ARM 64,您应该使用默认值(即/arch:arm8.0)。
MSVC使用的另一个开关是/favor,用于Intel与AMD的优化选择。默认值是/favor:BLEND,这是两者之间的一个很好的折衷。通常情况下,只有当您专门针对Xbox(/favor:AMD64)或Intel ATOM(/favor:ATOM)时,才会使用显式/favor开关。
例如,对于Xbox One,您使用/favor:AMD64 /arch:AVX。对于Xbox Series X,|S,你用/favor:AMD64 /arch:AVX2
对于Clang/Linux -march=native开关,我的理解是它从主机CPU获取信息以确定使用哪些设置,如果您正在构建仅打算在本地机器上运行的代码,这是有意义的。
Clang -march与MSVC /arch的另一个区别是,如果你使用显式的intrinsic,Clang * 真的希望 * 你指定一个足够高的-march来使它有效。MSVC只是相信你知道你在做什么,如果你使用一个特定的intrinsic,你也需要避免在x64编译器中使用/arch:SSE2,因为它实际上并不支持这个选项,因为它是必需的:
由于在CMake中没有一个很好的方法来告诉确切的目标架构,我使用一个构建变量设置为x86x64ARM,或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()

字符串

相关问题