如何确定要为体系结构启用或禁用的功能标记

时间:2017-02-02 19:41:52

标签: c++ linux bash gcc cpu-architecture

我有两台虚拟机;两者都运行在相同的Intel Xeon E5-2699v4(Broadwell-EP)平台上。但是,一台虚拟机(生产机器)驻留在具有禁用功能的主机上,而在另一台机器(构建机器)上启用它们。我们还有其他主机在Intel Xeon E5-2699v3平台(Haswell-EP)上运行,但这些主机将在稍后处理。我可以通过观察本地计算机的单行bash命令的结果来确定禁用哪些功能:

sort <(sshi vm1 "cat /proc/cpuinfo | grep flags | head -n 1 | sed -r 's/\s+/\t/g' | cut -f 3- | sed -r 's/\t/\n/g' | sort | uniq") <(sshi vm2 "cat /proc/cpuinfo | grep flags | head -n 1 | sed -r 's/\s+/\t/g' | cut -f 3- | sed -r 's/\t/\n/g' | sort | uniq") | uniq -u

...其中sshi是一个bash别名,用于确定连接时要使用的密钥文件,vm1是启用了所有功能且vm2为的机器的主机名 not 的计算机的主机名已启用所有功能。我认为这个oneline命令可以与循环配对,为编译器生成功能启用标志......

for feature in $(...); do echo "-mno-${feature}"; done

...生成一个列表:

-mno-abm
-mno-avx
-mno-avx2
-mno-bmi1
-mno-bmi2
-mno-eagerfpu
-mno-fma
-mno-hle
-mno-invpcid
-mno-movbe
-mno-pcid
-mno-pse36
-mno-rtm
-mno-tsc_adjust
-mno-xsave
-mno-xsaveopt

获取此列表并通过CMake将其传递给编译器:

LIST(APPEND COMMON_FLAGS /* paste flags here, along with other things such as -Wall -pedantic -Werror=etc */)
SET_PROPERTY(TARGET my_target PROPERTY COMPILE_OPTIONS ${COMMON_FLAGS})

...在g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)上使用devtoolset-4包提供的Oracle Linux Server 7.3时出现编译错误:

c++: error: unrecognized command line option ‘-mno-bmi1’
c++: error: unrecognized command line option ‘-mno-eagerfpu’
c++: error: unrecognized command line option ‘-mno-invpcid’
c++: error: unrecognized command line option ‘-mno-pcid’
c++: error: unrecognized command line option ‘-mno-pse36’
c++: error: unrecognized command line option ‘-mno-tsc_adjust’

只需将第一个错误更改为-mno-bmi而不是-mno-bmi1

即可解决第一个错误

我确实从GCC mailing list archive gcc -march=native -Q --help=target找到了这个有趣的消息。使用它来搜索功能并没有显示所有缺失的功能标志,所以这对我来说似乎是一个死胡同。

所以我的问题就是:

  1. 为什么功能集不能直接转换为功能标志 对于编译器?我当然会明白,如果它是一个新的&#34;特征 编译器根本不理解或支持......但是 将-mno-bmi1更改为-mno-bmi会向我建议那里有 只是对功能集命名的不一致。

  2. 是否有更好的方法可以编译完全优化的构建 启用了所有功能的机器可以定位机器 某些功能已停用?

  3. 是否存在描述哪些功能名称的映射 内核通过/proc/cpuinfo(或其他地方)和 编译器使用的名称?

1 个答案:

答案 0 :(得分:2)

  

为什么功能集不能直接转换为编译器的功能标志?我当然会明白,如果它是一个新的&#34;编译器根本不理解或支持的功能......但是将-mno-bmi1改为-mno-bmi告诉我,对于命名功能集的内容只是存在分歧。

我从未见过对此的讨论,所以我无法评论。也许你可以在gcc-help列表或内核邮件列表上询问。

我知道由于Clang和Solaris(以及FreeBSD,你必须检查/proc/cpuinfo),我花了相当多的时间来将/var/run/dmesg.boot标志映射到编译器标志。另请参阅Crypto++ ARM logicCrypto++ x86 logicCrypto++ Solaris logic

  

是否有更好的方法可以从机器上编译完全优化的构建,并启用所有功能以在禁用某些功能的情况下定位机器?

对于x86上的GCC(如i686和x86_64) GCC&gt; = 5.0,您可以使用多功能。请参阅GCC手册中的7.8 Function Multiversioning

对于ARM上的GCC,所有投注都已关闭,并且对于Clang,所有投注都将被取消。它在使用SunCC编译器的Solaris上也不起作用。

在实践中发生了什么样的事情&#34;步骤&#34;为功能设置,然后使用运行时CPU功能检测来选择实现(这是GCC多功能操作)。对于x86,步骤通常类似于:

  • 直C / C ++
  • SSE2
  • SSE3 + SSSE3
  • SSE4.1 + SSE4.2
  • AVX或AVX2

AVX / AVX2将分别包含BMI和BMI2。 Microsoft编译器仅使用SSE2和AVX以及AVX2。

还有通配符,如AES,CLMUL,RDRAND,RDSEED,SHA等。但大多数图书馆都不必担心它们。关注通常仅限于加密库。

我还注意到GCC在__MOVBE__和机器有能力时没有定义-march=native。另请参阅gcc-help邮件列表中的__MOVBE__ not defined when movbe feature is available?

对于ARM,通常是:

  • 直C / C ++
  • NEON

与x86一样,加密库经历的通配符包括PMULL,PMULL2,AES,SHA1,SHA2。

  

是否有某个地图描述了内核通过/ proc / cpuinfo(或其他地方)报告了哪些功能名称以及编译器使用的名称?

不是我知道的。您可以在Unix上查看What do the flags in /proc/cpuinfo mean?处的CPU功能。 Linux Stack Exchange,然后你从GCC的x86 OptionsARM Options等中找出arch选项。

就像我说的那样,我花了相当多的时间来测试Crypto ++,所以你大部分时间都可以从中删除它:

如果您想查看使用GCC多功能的示例,请查看Jack Lloyd's Botan

快速评论:

  

由Oracle Linux Server 7.3上的软件包devtoolset-4提供:

c++: error: unrecognized command line option ‘-mno-bmi1’
c++: error: unrecognized command line option ‘-mno-eagerfpu’

我猜测c++不是GCC(或更正确,g++),或者是旧的GCC 4.x编译器。

另一个快速评论......如果您只是想与Intel Xeon E5-2699v4(Broadwell-EP)和Intel Xeon E5-2699v3平台(Haswell-EP)相交,那么请使用以下内容:

CXXFLAGS="-march=x86_64 -msse2 -msse3 -msss3 -msse4_1 -msse4_2 -mavx -mbmi"

从低位起步并向天花板起作用。你不必弄清楚从-march=native中减去GCC的内容。而且你不必担心Clang对-march=native的行为有何不同。

关于-march=native行为的Clang错误报告: