O back-end do acelerador X10 pode fornecer rendimento significativamente maior para computação paralela baseada em gráfico, mas seu rastreamento adiado e compilação just-in-time podem às vezes levar a um comportamento não óbvio. Isso pode incluir recompilação frequente de rastreamentos devido a alterações na forma do gráfico ou do tensor, ou gráficos enormes que levam a problemas de memória durante a compilação.
Uma maneira de diagnosticar problemas é usar as métricas e contadores de execução fornecidos pelo X10. A primeira coisa a verificar quando um modelo está lento é gerar um relatório de métricas.
Métricas
Para imprimir um relatório de métricas, adicione uma chamada PrintX10Metrics()
ao seu programa:
import TensorFlow
...
PrintX10Metrics()
...
Isso registrará várias métricas e contadores no nível INFO
.
Compreendendo o relatório de métricas
O relatório inclui coisas como:
- Quantas vezes acionamos compilações XLA e o tempo total gasto na compilação.
- Quantas vezes lançamos um cálculo XLA e o tempo total gasto na execução.
- Quantos manipuladores de dados de dispositivos criamos/destruímos, etc.
Esta informação é reportada em termos de percentis das amostras. Um exemplo é:
Metric: CompileTime
TotalSamples: 202
Counter: 06m09s401ms746.001us
ValueRate: 778ms572.062us / second
Rate: 0.425201 / second
Percentiles: 1%=001ms32.778us; 5%=001ms61.283us; 10%=001ms79.236us; 20%=001ms110.973us; 50%=001ms228.773us; 80%=001ms339.183us; 90%=001ms434.305us; 95%=002ms921.063us; 99%=21s102ms853.173us
Também fornecemos contadores, chamados de variáveis inteiras que rastreiam o status interno do software. Por exemplo:
Counter: CachedSyncTensors
Value: 395
Advertências conhecidas
Tensor
s apoiados por X10 se comportam semanticamente como Tensor
s de modo ansioso padrão. No entanto, existem algumas advertências de desempenho e integridade:
Desempenho degradado devido a muitas recompilações.
A compilação XLA é cara. O X10 recompila automaticamente o gráfico sempre que novas formas são encontradas, sem intervenção do usuário. Os modelos precisam ver formas estabilizadas em algumas etapas de treinamento e, a partir desse ponto, nenhuma recompilação é necessária. Além disso, os caminhos de execução devem se estabilizar rapidamente pelo mesmo motivo: o X10 recompila quando um novo caminho de execução é encontrado. Resumindo, para evitar recompilações:
- Evite formas dinâmicas altamente variáveis. No entanto, um pequeno número de formas diferentes pode servir. Pad tensores para tamanhos fixos quando possível.
- Evite loops com diferentes números de iterações entre as etapas de treinamento. Atualmente, o X10 desenrola loops, portanto, diferentes números de iterações de loop se traduzem em diferentes caminhos de execução (desenrolados).
Um pequeno número de operações ainda não é suportado pelo X10.
Atualmente temos algumas operações que não são suportadas, seja porque não há uma boa maneira de expressá-las via XLA e formas estáticas (atualmente apenas
nonZeroIndices
) ou porque não há casos de uso conhecidos (várias operações de álgebra linear e inicialização multinomial) . Embora a segunda categoria seja fácil de resolver conforme necessário, a primeira categoria só pode ser abordada através da interoperabilidade com a CPU, implementação não XLA. Usar a interoperabilidade com muita frequência tem implicações significativas no desempenho devido às viagens de ida e volta do host e à fragmentação de um modelo totalmente fundido em vários rastreamentos. Os usuários são, portanto, aconselhados a evitar o uso de tais operações em seus modelos.No Linux, use
XLA_SAVE_TENSORS_FILE
(documentado na próxima seção) para obter o rastreamento de pilha Swift que chamou a operação não suportada. Os nomes das funções podem ser desmontados manualmente usandoswift-demangle
.
Obtenção e gráficos de traços
Se você suspeitar que há problemas com a maneira como os gráficos estão sendo rastreados ou quiser entender o processo de rastreamento, serão fornecidas ferramentas para efetuar logout e visualizar os rastreamentos. Você pode fazer com que o X10 efetue logout dos rastreamentos encontrados definindo a variável de ambiente XLA_SAVE_TENSORS_FILE
:
export XLA_SAVE_TENSORS_FILE=/home/person/TraceLog.txt
Esses logs de rastreamento vêm em três formatos: text
, hlo
e dot
, com formato configurável por meio da variável de ambiente XLA_SAVE_TENSORS_FMT:
export XLA_SAVE_TENSORS_FMT=text
Quando você executa seu aplicativo, a representação text
desconectada mostrará cada traço individual em uma notação de texto de alto nível usada pelo X10. A representação hlo
mostra a representação intermediária que é passada para o compilador XLA. Talvez você queira restringir o número de iterações em seus loops de treinamento ou cálculo para evitar que esses logs se tornem muito grandes. Além disso, cada execução do seu aplicativo será anexada a esse arquivo, portanto, você pode excluí-lo entre as execuções.
Definir a variável XLA_LOG_GRAPH_CHANGES
como 1 também indicará no log de rastreamento onde ocorreram alterações no gráfico. Isso é extremamente útil para encontrar locais onde ocorrerá a recompilação.
Para uma representação visual de um traço, a opção dot
desconectará os gráficos compatíveis com Graphviz. Se você extrair a parte de um traço que se parece com
digraph G {
...
}
em seu próprio arquivo, o Graphviz (supondo que esteja instalado) pode gerar um diagrama visual via
dot -Tpng trace.dot -o trace.png
Observe que definir a variável de ambiente XLA_SAVE_TENSORS_FILE
, especialmente quando usada em combinação com XLA_LOG_GRAPH_CHANGES
, terá um impacto negativo substancial no desempenho. Use-os apenas durante a depuração e não para operação regular.
Variáveis de ambiente adicionais
Variáveis de ambiente adicionais para depuração incluem:
XLA_USE_BF16
: Se definido como 1, transforma todos os valoresFloat
em BF16. Deve ser usado apenas para depuração, pois oferecemos precisão mista automática.XLA_USE_32BIT_LONG
: Se definido como 1, mapeia o tipo S4TFLong
para o tipo inteiro XLA de 32 bits. Na TPU, os cálculos inteiros de 64 bits são caros, portanto, definir esse sinalizador pode ajudar. Obviamente, o usuário precisa ter certeza de que os valores ainda cabem em um número inteiro de 32 bits.