Tentei limpar a página de manual do GCC para isso, mas ainda não entendi.
Qual é a diferença entre -march
e -mtune
?
Quando se usa apenas -march
, versus ambos? É possível apenas -mtune
?
Respostas:
Se você usar -march
, o GCC estará livre para gerar instruções que funcionam na CPU especificada, mas (normalmente) não em CPUs anteriores na família de arquitetura.
Se você apenas usar -mtune
, o compilador irá gerar código que funcione em qualquer um deles, mas irá favorecer as sequências de instruções que rodam mais rápido na CPU específica que você indicou. por exemplo, definir heurísticas de desenrolamento de loop apropriadamente para aquela CPU.
-march=foo
implica, a -mtune=foo
menos que você também especifique um diferente -mtune
. Este é um dos motivos pelos quais usar -march
é melhor do que apenas habilitar opções, por exemplo, -mavx
sem fazer nada sobre o ajuste.
Advertência: -march=native
em uma CPU que o GCC não reconhece especificamente, ainda habilitará novos conjuntos de instruções que o GCC pode detectar, mas sairá -mtune=generic
. Use um GCC novo o suficiente que saiba sobre sua CPU se você quiser fazer um bom código.
march
implica mtune
. Portanto, as respostas às suas objeções são não e sim, respectivamente.
mtune
e ideais march
diferentes. Esta postagem do blog ilumina esse ponto com os outros: lemire.me/blog/2018/07/25/…
Isso é o que eu pesquisei:
A -march=X
opção leva um nome de CPU X
e permite que o GCC gere código que usa todos os recursos deX
. O manual do GCC explica exatamente quais nomes de CPU significam quais famílias e recursos de CPU.
Como os recursos são geralmente adicionados, mas não removidos, um binário criado com -march=X
será executado na CPU X
, tem uma boa chance de ser executado em CPUs mais novas do X
queX
. Certos conjuntos de instruções (3DNow !, eu acho?) Podem ser específicos para um fornecedor de CPU em particular, fazendo uso deles provavelmente você obterá binários que não funcionam em CPUs concorrentes, mais recentes ou não.
A -mtune=Y
opção ajusta o código gerado para ser executado mais rápido do Y
que em outras CPUs em que possa ser executado. -march=X
implica -mtune=X
. -mtune=Y
não substituirá -march=X
, então, por exemplo, provavelmente não faz sentido -march=core2
e -mtune=i686
- seu código não será executado em nada mais antigo do que core2
qualquer coisa , por causa de-march=core2
, então por que diabos você deseja otimizar para algo mais antigo (menos cheio de recursos) do que core2? -march=core2 -mtune=haswell
faz mais sentido: não use nenhum recurso além do que core2
fornece (que ainda é muito mais do que o que -march=i686
você oferece!), mas otimize o código para haswell
CPUs muito mais novas , não para core2
.
Há também -mtune=generic
. generic
faz o GCC produzir código que funciona melhor nas CPUs atuais (significado das generic
mudanças de uma versão do GCC para outra). Existem rumores nos fóruns do Gentoo que -march=X -mtune=generic
produzem código que roda mais rápido do X
que o código produzido por -march=X -mtune=X
faz (ou apenas -march=X
, como -mtune=X
está implícito). Não faço ideia se isso é verdade ou não.
Geralmente, a menos que você saiba exatamente o que precisa, parece que o melhor caminho é especificar -march=<oldest CPU you want to run on>
e -mtune=generic
( -mtune=generic
está aqui para contrariar o implícito -mtune=<oldest CPU you want to run on>
, porque provavelmente você não deseja otimizar para a CPU mais antiga). Ou apenas -march=native
, se você vai rodar apenas na mesma máquina em que construiu.
-march=native
, você pode querer especificar -mtune=X
, porque o padrão ainda é -mtune=generic
, conforme discutido aqui: lemire.me/blog/2018/07/25/…
-march=native
implica tune=native
muito bem se você usar um GCC que saiba sobre sua CPU. Esse artigo apenas apresenta o caso ruim. As versões mais recentes do GCC criam códigos melhores em geral, especialmente ao usar novas instruções como AVX2 e AVX-512. E ter configurações de ajuste (como heurísticas de desenrolamento de loop) projetadas para sua CPU é definitivamente uma vantagem. Portanto, se você se preocupa o suficiente com o desempenho para usar essas opções, use um novo GCC, pelo menos um que conheça sua CPU, de preferência o atual relese estável.
tune=generic
para um membro mais novo da mesma família de microarquitetura, especialmente algo como Kaby Lake, que é literalmente idêntico à microarquitetura Skylake. Mas eu acho que ainda tem uma família / passo diferente, então um GCC que só conhecia Skylake e mais velhos poderia falhar em reconhecê-lo para ajuste.