我有两台虚拟机;两者都运行在相同的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
找到了这个有趣的消息。使用它来搜索功能并没有显示所有缺失的功能标志,所以这对我来说似乎是一个死胡同。
所以我的问题就是:
为什么功能集不能直接转换为功能标志
对于编译器?我当然会明白,如果它是一个新的&#34;特征
编译器根本不理解或支持......但是
将-mno-bmi1
更改为-mno-bmi
会向我建议那里有
只是对功能集命名的不一致。
是否有更好的方法可以编译完全优化的构建 启用了所有功能的机器可以定位机器 某些功能已停用?
是否存在描述哪些功能名称的映射
内核通过/proc/cpuinfo
(或其他地方)和
编译器使用的名称?
答案 0 :(得分:2)
为什么功能集不能直接转换为编译器的功能标志?我当然会明白,如果它是一个新的&#34;编译器根本不理解或支持的功能......但是将-mno-bmi1改为-mno-bmi告诉我,对于命名功能集的内容只是存在分歧。
我从未见过对此的讨论,所以我无法评论。也许你可以在gcc-help列表或内核邮件列表上询问。
我知道由于Clang和Solaris(以及FreeBSD,你必须检查/proc/cpuinfo
),我花了相当多的时间来将/var/run/dmesg.boot
标志映射到编译器标志。另请参阅Crypto++ ARM logic,Crypto++ x86 logic和Crypto++ 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,步骤通常类似于:
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,通常是:
与x86一样,加密库经历的通配符包括PMULL,PMULL2,AES,SHA1,SHA2。
是否有某个地图描述了内核通过/ proc / cpuinfo(或其他地方)报告了哪些功能名称以及编译器使用的名称?
不是我知道的。您可以在Unix上查看What do the flags in /proc/cpuinfo mean?处的CPU功能。 Linux Stack Exchange,然后你从GCC的x86 Options,ARM 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错误报告: