如何查看-march=native会激活哪些标志?

201

我正在使用GCC 4.3编译我的C++应用程序。为了避免手动选择优化标志,我正在使用-march=native,理论上应该添加适用于我所编译的硬件的所有优化标志。但是,我如何检查它实际使用的标志?

6个回答

180
您可以使用 -Q --help=target 选项:
gcc -march=native -Q --help=target ...
< p > -v 选项也可能有用。

您可以在此处查看关于--help选项的文档here


15
我建议这不是最佳选择。--help=target 的输出没有显示CPU缓存信息,而Elias和42n4都列出了这些方法。特别是,在Phenom上的gcc 4.9.2中,输出包括以下内容:“--param l1-cache-size = 64 --param l1-cache-line-size = 64 --param l2-cache-size = 512”。 - Daniel Santos
@DanielSantos:在我的系统上,使用“-v”选项确实会显示那些参数,尽管作为“cc1”命令行的一部分。 - thkala
在gcc版本5.4.0(Buildroot 2017.05-rc2-00016-gc7eaf50-dirty)上,使用-march=native会导致返回错误信息:汇编器消息: 错误:未知的本机架构 错误:无法识别选项-march=native。 因此,请删除-march=native,并且只需按照以下步骤即可在任何地方运行:gcc -Q --help=target - Oleg Kokorin
1
@Oleg - 这听起来像是GCC 5中的一个bug。在GCC 7中不存在这个问题。 - jww

159

要查看命令行标志,请使用:

gcc -march=native -E -v - </dev/null 2>&1 | grep cc1
如果您想查看由某些参数设置的编译器/预编译器定义,请执行以下操作:
echo | gcc -dM -E - -march=native

5
这个回答应该跟被采纳的那一个一样得到很多赞,尤其是因为它列出了 native 真正的含义。 - Iwillnotexist Idonotexist
7
如果我想进行跨平台编译,是应该给编译器提供定义和参数,还是只提供参数就可以了? - hanshenrik
相信参数足够。 - paleonix

29

应该是(-###-v 相似):

echo | gcc -### -E - -march=native 
展示gcc的“真实”本地标志。
您可以使用一个命令使它们更加“清晰”显示:
gcc -### -E - -march=native 2>&1 | sed -r '/cc1/!d;s/(")|(^.* - )//g'

你可以使用以下命令去掉所有 -mno-* 的标记:

gcc -### -E - -march=native 2>&1 | sed -r '/cc1/!d;s/(")|(^.* - )|( -mno-[^\ ]+)//g'

15

如果您想了解如何设置非本地交叉编译,我发现以下内容很有用:

在目标机器上,

% gcc -march=native -Q --help=target | grep march
-march=                               core-avx-i

然后在构建机上使用这个。
% gcc -march=core-avx-i ...

很遗憾,这不会包括所有的标志。 - Baptiste Wicht
@BaptisteWicht 在这种情况下,-march=native将包含哪些-march=core-avx-i不包含的标志,或者有哪些标志?谢谢! - rogerdpack
3
在这台电脑上(Sandy Bridge),使用 march=sandybridge 指令并不能启用 AVX 指令集(不知道原因),但使用 march=native 指令可以。另一个重要的区别是,只有使用 march=native 指令才能提取缓存大小。 - Baptiste Wicht
2
@BaptisteWicht 这很奇怪,在这里似乎可以工作(我猜):echo | gcc-6 -dM -E - -march=sandybridge | grep AVX #define __AVX__ 1,但缓存大小似乎确实不存在。 - rogerdpack

8

我要在这个问题上发表我的意见,并建议稍微详细一些的扩展elias的答案。从gcc 4.6开始,运行gcc -march=native -v -E - < /dev/null会以多余的-mno-*标志的形式产生越来越多的垃圾信息。以下内容将删除这些标志:

gcc -march=native -v -E - < /dev/null 2>&1 | grep cc1 | perl -pe 's/ -mno-\S+//g; s/^.* - //g;'

然而,我只在两个不同的CPU(Intel Core2和AMD Phenom)上验证了正确性,因此建议运行以下脚本,以确保可以安全地剥离所有这些 -mno-* 标志。

2021年编辑:确实有一些机器使用特定的-march值,但必须使用-mno-*来禁用某些隐含的ISA(指令集架构),而-march=native则无法实现该功能。

#!/bin/bash

gcc_cmd="gcc"

# Optionally supply path to gcc as first argument
if (($#)); then
    gcc_cmd="$1"
fi

with_mno=$(
    "${gcc_cmd}" -march=native -mtune=native -v -E - < /dev/null 2>&1 |
    grep cc1 |
    perl -pe 's/^.* - //g;'
)
without_mno=$(echo "${with_mno}" | perl -pe 's/ -mno-\S+//g;')

"${gcc_cmd}" ${with_mno}    -dM -E - < /dev/null > /tmp/gcctest.a.$$
"${gcc_cmd}" ${without_mno} -dM -E - < /dev/null > /tmp/gcctest.b.$$

if diff -u /tmp/gcctest.{a,b}.$$; then
    echo "Safe to strip -mno-* options."
else
    echo
    echo "WARNING! Some -mno-* options are needed!"
    exit 1
fi

rm /tmp/gcctest.{a,b}.$$

我并没有发现 gcc -march=native -v -E - < /dev/nullgcc -march=native -### -E - < /dev/null 之间有什么区别,除了一些参数被引用外,还有包含没有特殊字符的参数,因此我不确定在什么情况下会有任何实际区别。最后,请注意 --march=native 是在 gcc 4.2 中引入的,在此之前它只是一个无法识别的参数。

不错,这个 glean 函数也包含了缓存大小。 - rogerdpack
gcc版本为5.4.0(Buildroot 2017.05-rc2-00016-gc7eaf50-dirty)返回错误:未知架构“native” - Oleg Kokorin
奥列格:你用的是什么架构?“本地”的支持可能只在某些架构上可用。 - Daniel Santos

1
有一个resolve-march-native可以完美解决这个问题:它解析GCC的输出,并将多次调用GCC的输出合并为最终答案。例如:
# resolve-march-native --vertical
-march=sandybridge
-maes
--param=l1-cache-line-size=64
--param=l1-cache-size=32
--param=l2-cache-size=3072

还有distccflags,但它似乎已经停用

附注:我是resolve-march-native的作者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接