GCC: como o march é diferente do mtune?

87

Tentei limpar a página de manual do GCC para isso, mas ainda não entendi.

Qual é a diferença entre -marche -mtune?

Quando se usa apenas -march, versus ambos? É possível apenas -mtune?

Jameson
fonte

Respostas:

97

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=fooimplica, a -mtune=foomenos 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, -mavxsem fazer nada sobre o ajuste.

Advertência: -march=nativeem 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.

James Youngman
fonte
10
Não responde se faz sentido usar ambos ou se mtune é redundante quando definido com o mesmo valor.
Pavel Šimerda
12
@PavelŠimerda Intuitivamente, a resposta está implícita na definição das 2 características. Além disso, a documentação afirma explicitamente que marchimplica mtune. Portanto, as respostas às suas objeções são não e sim, respectivamente.
sublinhado_d
Obrigado por explicar isso tão elegantemente! Você torna isso fácil de entender.
Rahim Khoja
5
As pessoas precisam de um tl; dr: Use -march se você executá-lo SOMENTE no seu processador, use -mtune se quiser que ele seja seguro para outros processadores.
j riv
3
Os usuários também devem entender que compiladores mais antigos (lançados antes que alguma CPU não existisse) podem resultar em combinações mtunee ideais marchdiferentes. Esta postagem do blog ilumina esse ponto com os outros: lemire.me/blog/2018/07/25/…
qneill
52

Isso é o que eu pesquisei:

A -march=Xopção leva um nome de CPU Xe 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=Xserá executado na CPU X, tem uma boa chance de ser executado em CPUs mais novas do XqueX . 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=Yopção ajusta o código gerado para ser executado mais rápido do Yque em outras CPUs em que possa ser executado. -march=Ximplica -mtune=X. -mtune=Ynão substituirá -march=X, então, por exemplo, provavelmente não faz sentido -march=core2e -mtune=i686- seu código não será executado em nada mais antigo do que core2qualquer 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=haswellfaz mais sentido: não use nenhum recurso além do que core2fornece (que ainda é muito mais do que o que -march=i686você oferece!), mas otimize o código para haswellCPUs muito mais novas , não para core2.

Há também -mtune=generic. genericfaz o GCC produzir código que funciona melhor nas CPUs atuais (significado das genericmudanças de uma versão do GCC para outra). Existem rumores nos fóruns do Gentoo que -march=X -mtune=genericproduzem código que roda mais rápido do Xque o código produzido por -march=X -mtune=Xfaz (ou apenas -march=X, como -mtune=Xestá 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=genericestá 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.

LRN
fonte
4
Mas se você usar -march=native, você pode querer especificar -mtune=X, porque o padrão ainda é -mtune=generic, conforme discutido aqui: lemire.me/blog/2018/07/25/…
Roland Weber
@RolandWeber: Isso só acontece se você usar um GCC muito antigo para saber sobre sua CPU. -march=nativeimplica tune=nativemuito 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.
Peter Cordes
É uma pena que o GCC não possa fazer nada melhor do que tune=genericpara 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.
Peter Cordes