Atualizações de back-end do MSVC no Visual Studio 2019 Preview 2: Novas otimizações, OpenMP e melhorias na taxa de compilação


No Visual Studio 2019 Preview 2, continuamos aprimorando o back-end do C ++ com novos recursos, otimizações novas e aprimoradas, aprimoramentos de produção e alterações na qualidade de vida.


Original no blog

Novos recursos


  • Adicionada uma nova opção de linha de comando embutida: -Ob3. -Ob3 é uma versão mais agressiva do -O2. -O2 (otimizar o binário para velocidade) ainda implica -Ob2 por padrão, mas isso pode mudar no futuro. Se você achar que o compilador está sublinhado, considere passar -O2 -Ob3.
  • Adicionado suporte básico à vetorização OpenMP SIMD, que é o recurso OpenMP mais amplamente usado nas bibliotecas de aprendizado de máquina (ML). Nosso estudo de caso é a biblioteca Intel MKL-DNN, usada como base para outras bibliotecas ML de código aberto conhecidas, incluindo o Tensor Flow. Isso pode ser ativado com um novo comutador CL -openmp: experimental. Isso permite que os loops anotados com "#pragma omp simd" sejam potencialmente vetorizados. A vetorização não é garantida e os loops anotados, mas não vetorizados, receberão um aviso relatado. Não há suporte para cláusulas SIMD, elas serão simplesmente ignoradas com um aviso relatado.
  • Adicionado um novo manipulador de exceção C ++ __CxxFrameHandler4 que reduz a sobrecarga de metadados de manipulação de exceção em 66%. Isso fornece uma melhoria total de até 15% no tamanho binário em binários que usam grandes quantidades de manipulação de exceção em C ++. Atualmente desativado, tente testá-lo passando “/ d2FH4” ao compilar com o cl.exe. Observe que / d2FH4 é de outro modo não documentado e sem suporte a longo prazo. No momento, isso não é suportado em aplicativos UWP, pois o tempo de execução UWP ainda não possui esse recurso.
  • Para oferecer suporte à vetorização manual de loops contendo chamadas para funções da biblioteca matemática e certas outras operações como divisão inteira, o MSVC agora suporta funções intrínsecas da SVML (Short Vector Math Library) que calculam os equivalentes de vetores. O suporte para vetores de 128, 256 e 512 bits está disponível para a maioria das funções, com as exceções listadas abaixo. Observe que essas funções não configuram errno. Consulte o Intel Intrinsic Guide para obter definições das funções suportadas.
    As exceções incluem:
    • A divisão e o restante combinados de números inteiros de vetores estão disponíveis apenas para elementos de 32 bits e comprimentos de vetor de 128 e 256 bits. Use funções separadas de divisão e restante para outros tamanhos de elemento e comprimentos de vetor.
    • A raiz quadrada SVML está disponível apenas nos comprimentos de vetor de 128 e 256 bits. Você pode usar as funções _mm512_sqrt_pd ou _mm512_sqrt_ps para vetores de 512 bits.
    • Apenas versões vetoriais de 512 bits das funções rint e nearbyint estão disponíveis. Em muitos casos, você pode usar funções redondas, por exemplo, use _mm256_round_ps (x, _MM_FROUND_CUR_DIRECTION) como uma versão vetorial de rint de 256 bits ou _mm256_round_ps (x, _MM_FROUND_TO_NEAREST_INT) paraintint nas proximidades .
    • Somente recíproco de 512 bits é fornecido. Você pode calcular o equivalente usando as funções set1 e div, por exemplo, recíproco de 256 bits pode ser calculado como _mm256_div_ps (_mm256_set1_ps (1.0f), (x)) .
    • Existem funções SVML para raiz quadrada complexa de precisão única, logaritmo e exponenciação apenas em comprimentos vetoriais de 128 e 256 bits.

Otimizações novas e aprimoradas


  • Memsets desenrolados e inicializações de bloco agora usarão instruções SSE2 (ou instruções AVX, se permitido). O limite de tamanho para o que será desenrolado aumentou de acordo (compile para tamanho com SSE2: o limite de desenrolamento se move de 31 para 63 bytes, compile para velocidade com SSE2: limite se move de 79 para 159 bytes).
  • Otimizou a geração de código para pequenos conjuntos de mems, direcionados principalmente para funções protegidas por initall .
  • Melhorias na eliminação redundante de armazenamento do SSA Optimizer : melhor análise de escape e manipulação de loops
  • O compilador reconhece memmove () como uma função intrínseca e otimiza de acordo. Isso melhora a geração de código para operações criadas no memmove (), incluindo std :: copy () e outro código de biblioteca de nível superior, como construção std :: vector e std :: string
  • O otimizador faz um trabalho melhor ao otimizar operações curtas e de comprimento fixo memmove (), memcpy () e memcmp ().
  • Implementação da otimização de duplicação de comutadores para melhor desempenho dos comutadores dentro de hot loops. Duplicamos os saltos do comutador para ajudar a melhorar a precisão da previsão de ramificação e, consequentemente, o desempenho do tempo de execução.
  • Adicionadas simplificações aritméticas e dobragem constante para expressões usando SIMD (vetor) intrínseco, para formas flutuantes e inteiras. A maioria das otimizações de expressão usuais agora lida com intrínsecas SSE2 e AVX2, a partir do código do usuário ou como resultado da vetorização automática.
  • Vários novos padrões escalares de adição múltipla combinada (FMA) são identificados com / arch: AVX2 / fp: fast. Isso inclui as seguintes expressões comuns: (x + 1.0) * y; (x – 1.0) * y; (1.0 – x) * y; (-1.0 – x) * y (x + 1.0) * y; (x – 1.0) * y; (1.0 – x) * y; (-1.0 – x) * y
  • Sequências de código que inicializam um valor __m128 SIMD (vetor) elemento por elemento são identificadas e substituídas por um _mm_set_ps intrínseco. Isso permite que as novas otimizações do SIMD considerem o valor como parte das expressões, útil principalmente se o valor tiver apenas elementos constantes. Uma atualização futura suportará mais tipos de valor.
  • A eliminação de subexpressão comum (ECE) é mais eficaz na presença de variáveis ​​que podem ser modificadas de maneira indireta, porque o endereço é utilizado.
  • Cópias de estrutura / classe inúteis estão sendo removidas em vários outros casos, incluindo cópias para parâmetros e funções de saída que retornam um objeto. Essa otimização é especialmente eficaz em programas C ++ que transmitem objetos por valor.
  • Adicionada uma análise mais poderosa para extrair informações sobre variáveis ​​do fluxo de controle (instruções if / else / switch), usadas para remover ramificações que podem ser sempre verdadeiras ou falsas e para melhorar a estimativa do intervalo variável. O código usando gsl :: span vê melhorias, algumas verificações de intervalo desnecessárias estão sendo removidas.
  • A otimização da destirtualização agora terá oportunidades adicionais, como quando as classes são definidas em namespaces anônimos.

Construir melhorias na taxa de transferência


  • Filtre as informações de depuração durante a compilação com base nos símbolos e tipos referenciados para reduzir o tamanho da seção de depuração e melhorar o rendimento do vinculador. A atualização de 15.9 para 16.0 pode reduzir o tamanho da entrada para o vinculador em até 40%.
  • Melhorias no tempo do link na fusão e criação do tipo PDB.
  • A atualização para 16.0 a partir de 15.9 pode melhorar o tempo de link em até uma velocidade de 2X. Por exemplo, a vinculação do Chrome resultou em uma aceleração do tempo do link 1,75X ao usar / DEBUG: full e uma aceleração do tempo do link 1,4X no uso do / link rápido / DEBUG :.

Melhorias na Qualidade de Vida


  • O compilador exibe nomes e caminhos de arquivos usando o revestimento fornecido pelo usuário, onde anteriormente o compilador exibia nomes e caminhos de arquivos com letras minúsculas.
  • O novo vinculador agora reportará símbolos potencialmente correspondentes para símbolos não resolvidos, como:

 main.obj : error LNK2019: unresolved external symbol _foo referenced in function _main Hint on symbols that are defined and could potentially match: "int __cdecl foo(int)" (?foo@@YAHH@Z) "bool __cdecl foo(double)" (?foo@@YA_NN@Z) @foo@0 foo@@4 main.exe : fatal error LNK1120: 1 unresolved externals 
  • Ao gerar uma biblioteca estática, não é mais necessário passar o sinalizador / LTCG para LIB.exe.
  • Adicionada uma opção de vinculador / LINKREPROTARGET: [binary_name] para gerar apenas uma reprodução de link para o binário especificado. Isso permite que% LINK_REPRO% ou / LINKREPRO: [directory_name] seja definido em uma compilação grande com vários vínculos, e o vinculador gerará apenas a reprodução do binário especificado em / linkreprotarget.

Adoraríamos que você baixasse o Visual Studio 2019 e experimente. Como sempre, agradecemos seus comentários. Podemos ser contatados pelos comentários abaixo ou por e-mail ( visualcpp@microsoft.com ). Se você encontrar problemas com o Visual Studio ou MSVC ou tiver uma sugestão para nós, informe-nos através de Ajuda> Enviar comentários> Relatar um problema / Fornecer uma sugestão no produto ou na Comunidade de desenvolvedores . Você também pode encontrar-nos no Twitter ( @VisualC ) e no Facebook (msftvisualcpp).

Source: https://habr.com/ru/post/pt437670/


All Articles