Conheça 8 flags para melhorar drasticamente a velocidade do seu software
Nós já fizemos um vídeo sobre flags que servem tanto para o GCC quanto para o Clang, no entanto, aquelas dicas tem instruções gerais para compilação. Nesse artigo vamos especificar mais o objetivo em "tempo de compilação" que influenciam diretamente do desempenho do binário tornando a velocidade em "tempo de execução", melhor! 01. O básico A flag -fsanitize=address e todas as outras do sanitize(libasan), do Google, que foi implementada nativamente pelo Projeto GNU serve para verificar memory leaks, violação de memória e entre outras falhas relacionadas. Mas, ela deve ser usada somente durante o desenvolvimento, quando você for disponibilizar para produção, ou seja, a versão release o ideal é criar o Makefile, ou CMake ou qualquer outra ferramenta de compilação sem essa flag, aliás, é bom remover qualquer outra flag de debug, inclusive: -g, -Wall, -Werror, -pedantic, -Wpedantic,... Pois, elas, principalmente a -fsanitize=address deixam a execução do binário muito lenta. Você pode substituir pelo otimizador, por exemplo, -O1, -O2 ou -O3: -O1 (Otimização básica) - Ativa otimizações que melhoram a performance sem aumentar significativamente o tempo de compilação. Exemplos: eliminação de código morto, propagação de constantes, inlining limitado. -O2 (Otimização moderada) - Inclui todas as otimizações de -O1 e adiciona mais agressivas que ainda mantêm a confiabilidade do código. Exemplos: desdobramento de loops (loop unrolling), eliminação de subexpressões comuns, melhor agendamento de instruções. -O3 (Otimização agressiva) - Inclui todas as otimizações de -O2 e adiciona novas ainda mais agressivas, como maior inlining e vetorização de loops. Pode aumentar o tamanho do código e, em alguns casos, reduzir a performance por over-otimização. E ainda, existe também a -Ofast, apesar dela ser a mais agressiva de todas e quase equivalente a -O3, ela pode otimizar completamente o código o deixando ainda mais veloz, pois ela ainda inclui a flag -ffast-math, isso pode ser bom, mas o ideal é fazer testes, pois alguns cálculos de precisão, principalmente para os tipos double e float podem ter resultado inesperados, pois ela pode diminuir a quantidade de dígitos significativos, além de poder quebrar com os padrões C e C++. No entanto, na maioria dos casos, ela é indicada para o release, exemplo: g++ -Ofast main.cpp Se quiser uma fusão menos conflitante, use junto com -ffp-contract=fast: Permite fusão de operações de ponto flutuante, como FMA (Fused Multiply-Add). Resumindo: Use -Ofast se precisão numérica exata não for crítica e quiser extrair o máximo de desempenho. 02. Ajuste específico para a arquitetura do processador A flag -march=native permite que o compilador gere código otimizado para a arquitetura da sua CPU: g++ -Ofast -march=native main.cpp Usar em combinação com -Ofast pode ser uma ótima ideia para o desempenho. Isso permite que o compilador use instruções avançadas do seu processador, como SSE, AVX, etc. Se precisar distribuir o binário para outras máquinas, escolha um valor específico em vez de native, como -march=haswell, -march=znver3, etc. Resumindo: A flag -march=native, use, caso queira, para permitir que o compilador gere código otimizado para a arquitetura da sua CPU. 03. Paralelismo com OpenMP Se o código for paralelizável, adicione suporte ao OpenMP para aproveitar múltiplos núcleos da CPU: g++ -Ofast -march=native -fopenmp main.cpp Também com combinação com as flags citadas acima. Isso permite que loops e outras partes do código rodem em paralelo. O OpenMP (do inglês Open Multi-Processing, ou Multi-processamento aberto) é uma interface de programação de aplicativo(API) para a programação multi-processo de memória compartilhada em múltiplas plataformas. Permite acrescentar simultaneidade aos programas escritos em C, C++ e Fortran sobre a base do modelo de execução fork-join. 04. Melhorar uso do cache da CPU As flags -funroll-loops e -fprefetch-loop-arrays ajudam a melhorar a execução de loops: g++ -Ofast -march=native -funroll-loops -fprefetch-loop-arrays main.cpp Também com combinação com as flags citadas acima. Se usássemos elas no vídeo sobre Ranking das Linguagens de Programação, C++ e C deixaria as que ficaram atrás delas, ainda mais distantes!

Nós já fizemos um vídeo sobre flags que servem tanto para o GCC quanto para o Clang, no entanto, aquelas dicas tem instruções gerais para compilação.
Nesse artigo vamos especificar mais o objetivo em "tempo de compilação" que influenciam diretamente do desempenho do binário tornando a velocidade em "tempo de execução", melhor!
01. O básico
A flag -fsanitize=address
e todas as outras do sanitize(libasan
), do Google, que foi implementada nativamente pelo Projeto GNU serve para verificar memory leaks, violação de memória e entre outras falhas relacionadas.
Mas, ela deve ser usada somente durante o desenvolvimento, quando você for disponibilizar para produção, ou seja, a versão release o ideal é criar o Makefile, ou CMake ou qualquer outra ferramenta de compilação sem essa flag, aliás, é bom remover qualquer outra flag de debug, inclusive: -g
, -Wall
, -Werror
, -pedantic
, -Wpedantic
,...
Pois, elas, principalmente a -fsanitize=address
deixam a execução do binário muito lenta. Você pode substituir pelo otimizador, por exemplo, -O1
, -O2
ou -O3
:
-O1
(Otimização básica) - Ativa otimizações que melhoram a performance sem aumentar significativamente o tempo de compilação. Exemplos: eliminação de código morto, propagação de constantes, inlining limitado.-O2
(Otimização moderada) - Inclui todas as otimizações de-O1
e adiciona mais agressivas que ainda mantêm a confiabilidade do código. Exemplos: desdobramento de loops (loop unrolling), eliminação de subexpressões comuns, melhor agendamento de instruções.-O3
(Otimização agressiva)
- Inclui todas as otimizações de-O2
e adiciona novas ainda mais agressivas, como maior inlining e vetorização de loops. Pode aumentar o tamanho do código e, em alguns casos, reduzir a performance por over-otimização.
E ainda, existe também a -Ofast
, apesar dela ser a mais agressiva de todas e quase equivalente a -O3
, ela pode otimizar completamente o código o deixando ainda mais veloz, pois ela ainda inclui a flag -ffast-math
, isso pode ser bom, mas o ideal é fazer testes, pois alguns cálculos de precisão, principalmente para os tipos double
e float
podem ter resultado inesperados, pois ela pode diminuir a quantidade de dígitos significativos, além de poder quebrar com os padrões C e C++.
No entanto, na maioria dos casos, ela é indicada para o release, exemplo:
g++ -Ofast main.cpp
Se quiser uma fusão menos conflitante, use junto com
-ffp-contract=fast
: Permite fusão de operações de ponto flutuante, como FMA (Fused Multiply-Add).
Resumindo:
Use -Ofast
se precisão numérica exata não for crítica e quiser extrair o máximo de desempenho.
02. Ajuste específico para a arquitetura do processador
A flag -march=native
permite que o compilador gere código otimizado para a arquitetura da sua CPU:
g++ -Ofast -march=native main.cpp
Usar em combinação com
-Ofast
pode ser uma ótima ideia para o desempenho.
Isso permite que o compilador use instruções avançadas do seu processador, como SSE, AVX, etc.
Se precisar distribuir o binário para outras máquinas, escolha um valor específico em vez de native, como -march=haswell
, -march=znver3
, etc.
Resumindo:
A flag -march=native
, use, caso queira, para permitir que o compilador gere código otimizado para a arquitetura da sua CPU.
03. Paralelismo com OpenMP
Se o código for paralelizável, adicione suporte ao OpenMP para aproveitar múltiplos núcleos da CPU:
g++ -Ofast -march=native -fopenmp main.cpp
Também com combinação com as flags citadas acima.
Isso permite que loops e outras partes do código rodem em paralelo.
O OpenMP (do inglês Open Multi-Processing, ou Multi-processamento aberto) é uma interface de programação de aplicativo(API) para a programação multi-processo de memória compartilhada em múltiplas plataformas. Permite acrescentar simultaneidade aos programas escritos em C, C++ e Fortran sobre a base do modelo de execução fork-join.
04. Melhorar uso do cache da CPU
As flags -funroll-loops
e -fprefetch-loop-arrays
ajudam a melhorar a execução de loops:
g++ -Ofast -march=native -funroll-loops -fprefetch-loop-arrays main.cpp
Também com combinação com as flags citadas acima.
Se usássemos elas no vídeo sobre Ranking das Linguagens de Programação, C++ e C deixaria as que ficaram atrás delas, ainda mais distantes!