Guia de desempenho

O Cloud TPU oferece alto desempenho a baixo custo. Você pode melhorar ainda mais o desempenho do Cloud TPU ajustando os parâmetros de configuração de acordo com seu aplicativo, bem como identificando e resolvendo quaisquer gargalos que limitam o desempenho.

Este guia ajuda a maximizar o desempenho do Cloud TPU ao mostrar como:

Além disso, os recursos abaixo descrevem como:

Desempenho do compilador XLA

O XLA é um compilador para machine learning que pode produzir binários para TPUs, CPUs, GPUs e outras plataformas. Ele faz parte da base de código padrão do TensorFlow. Os modelos do TensorFlow para o Cloud TPU são traduzidos em um gráfico do XLA, que é compilado pelo mesmo em um executável de TPU. Para saber mais sobre como o XLA e o TensorFlow interagem, consulte a página sobre a visão geral do XLA.

O hardware do Cloud TPU é diferente das CPUs e GPUs. Em modo geral, as CPUs podem ser caracterizadas pelo fato de terem um baixo número de linhas de execução de alto desempenho. Já as GPUs têm um número muito alto de linhas de execução de baixo desempenho. Por sua vez, um Cloud TPU, com unidade de matriz de 128 x 128, pode ser considerado como uma única linha de execução muito poderosa que pode realizar 16 mil operações por ciclo ou como linhas de execução de 128 x 128 mínimas e simples que estão conectadas como um canal. Proporcionalmente, com relação à memória, é preferível ter múltiplos de 8 (flutuantes), assim como múltiplos de 128 para operações direcionadas à unidade de matriz.

Consequências da divisão em blocos

As matrizes no Cloud TPU estão em blocos. Isso envolve o preenchimento de uma das dimensões em um múltiplo de 8 e de uma dimensão diferente em um múltiplo de 128. O XLA realiza transformações no layout dos dados. Os dados são organizados na memória de forma que o hardware possa processar os dados com eficiência. Essas transformações são guiadas pela heurística. Ainda que benéficas na maioria dos casos, sempre é possível que o compilador faça algo errado. Para conseguir o desempenho mais elevado, faça experimentos com configurações de modelo diferentes.

Regra geral: minimize o custo do preenchimento

Uma consequência de usar um esquema de memória em blocos é que a eficiência depende da quantidade de memória desperdiçada na sobrecarga de preenchimento. Para usar o Cloud TPU da maneira mais eficiente, use tamanhos que minimizem a sobrecarga da divisão em blocos.

Por exemplo, um resultado de convolução tem (1) lote, (2) característica de saída e (3) dimensões espaciais de saída. Uma das dimensões do lote ou da característica de saída será preenchida com um múltiplo de 8, enquanto a outra será preenchida com um múltiplo de 128. As dimensões espaciais de saída não serão preenchidas.

Em geral, em uma operação com dimensões espaciais (tf.nn.pool, tf.conv2d etc.), as dimensões espaciais nunca são preenchidas.

Regra geral: escolha valores eficientes para as dimensões de lote e de característica

As dimensões de lote e de característica estão sujeitas a preenchimento. Portanto, tenha cuidado ao determinar os tamanhos de lote e de característica. Para fazer o melhor uso da unidade de matriz de 128 x 128, procure valores razoavelmente grandes (maiores ou iguais a 128) de lotes ou características, preferencialmente de ambos.

Na maioria dos casos, um tamanho de lote de 128 é suficiente para manter a unidade de matriz do Cloud TPU totalmente ocupada. A execução com tamanhos de lote maiores também funciona bem no Cloud TPU. No entanto, é recomendável usar um múltiplo de 128 como tamanho de lote. Se seu modelo não funciona nessa configuração, use um tamanho de lote que seja múltiplo de 8 para minimizar o impacto do preenchimento.

Da mesma forma, as dimensões de característica também são mapeadas para uma dimensão que é preenchida com 8 ou 128, dependendo das decisões tomadas pelo algoritmo de layout do XLA. Isso significa que a dimensão de característica desperdiça a menor quantidade de espaço com múltiplos de 8 ou 128.

Fusão

A fusão é uma técnica geral que o compilador XLA usa para otimizar programas. Uma operação fundida é a combinação de várias operações integrantes que devem ser executadas juntas.

Por exemplo, imagine a seguinte série de operações:

tmp = tf.add(x, y)
result = tf.multiply(tmp, z)

Esse código é aproximadamente equivalente ao seguinte código falso:

for (i = 0; i < element_count; i++) {
  tmp[i] = x[i] + y[i];
}

for (i = 0; i < element_count; i++) {
  result = tmp[i] * z[i];
}

Com a fusão, os acessos à matriz acontecem ao mesmo tempo:

for (i = 0; i < element_count; i++) {
  result = (x[i] + y[i]) * z[i];
}

Nesse exemplo, o número de idas e voltas à memória é reduzido e o XLA não precisa alocar espaço para "tmp".

A fusão é um tipo de otimização essencial e traz diversos benefícios para o Cloud TPU:

  • Reduz as transferências de memória ao eliminar a necessidade de armazenar resultados intermediários na memória principal, que é um processo lento.
  • Proporciona maior utilização das unidades de hardware que, caso contrário, ficariam ociosas.
  • Pode reduzir a quantidade de memória usada pelo modelo porque menos buffers precisam estar ativos ao mesmo tempo.

Transmissão

A transmissão ocorre implicitamente quando dois tensores com formas diferentes, mas compatíveis, são combinados.

Por exemplo, tf.add(vector, matrix) requer que o vetor seja transmitido na forma da matriz. O resultado da operação tem a mesma forma que a matriz. Para saber mais, consulte o guia de transmissão de matrizes.

Muitas vezes, as transmissões podem ser fundidas com os elementos que as consome, mas obrigar que uma transmissão seja materializada resulta em baixo desempenho e aumento da pressão sobre a memória.

No exemplo a seguir, na adição de um vetor a uma matriz há uma transmissão implícita que não pode ser fundida com "argmax" e resulta em uma transmissão materializada:

tf.argmax(tf.add(vector, zero_matrix), axis=0)

Recomendações específicas para funções do TensorFlow

Veja a lista completa de operações do TensorFlow disponíveis no Cloud TPU.

tf.matmul

  • A transposição do resultado de qualquer um dos operandos é efetivamente gratuita.
  • Observe que tf.matmul é compatível com a fusão na entrada e na saída. Isso significa que as funções de ativação ou as tendências aplicadas diretamente à saída de tf.matmul têm baixa sobrecarga.

tf.nn.conv_n_d, tf.nn.depthwise_conv2d, tf.nn.separable_conv2d

  • Para as ativações, as dimensões de lote e de característica são preenchidas por um múltiplo de 8 ou 128.
    • Primeiro, o XLA rastreia o tamanho mais comum entre as dimensões de lote para convoluções no módulo. Isso ajuda a distinguir entre convoluções progressivas, convoluções de gradiente de ativação e convoluções de gradiente do kernel.
    • Se o tamanho de lote mais comum for maior ou igual a 64:
      • o lote é preenchido com um múltiplo de 128 e a característica é preenchida com um múltiplo de 8 para convoluções progressivas e regressivas;
      • o lote é preenchido com um múltiplo de 8 e a característica é preenchida com um múltiplo de 128 para as convoluções de atualização de gradiente.
    • Se o tamanho de lote mais comum for menor que 64:
      • o lote é preenchido com um múltiplo de 8 e a característica é preenchida com um múltiplo de 128 para convoluções progressivas e regressivas;
      • o lote é preenchido com um múltiplo de 128 e a característica é preenchida com um múltiplo de 8 para as convoluções de atualização de gradiente;
      • a transposição das ativações antes de enviá-las para uma convolução será gratuita se ela apenas alternar as dimensões de característica de entrada e de lote.
  • No caso do kernel, as dimensões de características de entrada e saída são preenchidas com um múltiplo de 8 ou 128. A determinação exata é influenciada pelos produtores e outros consumidores do kernel.
    • A transposição de um kernel antes de enviá-lo para uma convolução será gratuita se ela apenas alternar as dimensões de características de entrada e saída.
  • No caso do resultado, as dimensões de lote e de característica são preenchidas com um múltiplo de 8 ou 128.
    • A transposição do resultado de uma convolução será gratuita se ela apenas alternar as dimensões de lote e de característica de saída.
  • Observe que tf.nn.conv_n_d é compatível com a fusão no resultado, nas ativações e/ou no kernel. Isso significa que as funções de ativação ou as tendências aplicadas diretamente à saída têm baixa sobrecarga.

tf.nn.avg_pool, tf.nn.max_pool

  • As regras de preenchimento serão aplicadas se as dimensões espaciais forem maiores do que o lote e a característica. Cada combinação de lote e característica pode ser preenchida com um múltiplo de 8 ou 128.
  • Normalmente, o layout de uma operação de pool corresponde às convoluções que entram ou saem dele.
  • O cálculo do gradiente de tf.nn.max_pool pode ser mais lento do que a função tf.nn.avg_pool equivalente. Considere a possibilidade de mudar do pooling máximo para o médio sempre que possível.

tf.concat, tf.slice, tf.strided_slice

  • Evite frações e concatenações desnecessários. Frações e concatenações em uma dimensão que foi preenchida são consideravelmente mais custosas.
    • A movimentação de dados será minimizada se a dimensão da fração não tiver sobrecarga de preenchimento.

tf.transpose

  • A transposição de qualquer um dos operandos de tf.matmul ou do respectivo resultado é gratuita.
  • A transposição de ativações de tf.conv_n_d será gratuita se ela alternar as dimensões de lote e de característica de entrada.
  • A transposição do kernel de tf.conv_n_d será gratuita se ela alternar as dimensões de características de entrada e saída.
  • A transposição do resultado de tf.conv_n_d será gratuita se ela alternar as dimensões de lote e de característica de saída.

tf.batch_to_space, tf.space_to_batch, tf.space_to_depth, tf.depth_to_space

  • Essas funções são dispendiosas porque envolvem a movimentação de dados de dimensões preenchidas para não preenchidas e vice-versa.

tf.reshape

  • Quando dados são movimentados em uma dimensão preenchida, a reconfiguração da forma pode ser dispendiosa no Cloud TPU.
  • Talvez seja útil reconfigurar a forma dos dados para R1 no host e, depois, reconfigurar de volta para uma forma de dimensão mais elevada no dispositivo, se o preenchimento for substancial. Isso pode aumentar a eficiência das transferências entre o host e o dispositivo.
    • Essa ação também pode ajudar durante os picos de utilização de memória, porque o parâmetro compactado pode ser descompactado sob demanda.

tf.random_uniform, tf.distributions.Bernoulli, tf.random_normal, tf.multinomial

  • A geração de números pseudoaleatórios para distribuições uniformes ou de Bernoulli é muito rápida.
  • As distribuições normais são um pouco mais dispendiosas do que as distribuições uniformes ou de Bernoulli.
  • A geração de números pseudoaleatórios para distribuições categóricas/multinomiais é consideravelmente mais dispendiosa.

tf.reduce_all, tf.reduce_any, tf.reduce_logsumexp, tf.reduce_max, tf.reduce_min, tf.reduce_prod, tf.reduce_sum

  • A fusão permite realizar em paralelo várias reduções com a mesma forma de entrada e de saída.
    • Se possível, reescreva as cadeias sequenciais das reduções em cadeias paralelas.
  • As reduções são compatíveis com a fusão de operações elemento a elemento nas entradas, mas não nas saídas. Quando possível, reescreva expressões para promover a fusão. Por exemplo:

        tf.multiply(tf.reduce_sum(x), y)
    

    em:

        tf.reduce_sum(tf.multiply(x, y))
    

tf.nn.batch_normalization, tf.nn.fused_batch_norm, tf.layers.batch_normalization

  • O compilador do Cloud TPU pode reduzir de forma eficiente as variantes fundidas do TensorFlow na normalização em lote. Usá-las pode ser consideravelmente mais eficiente do que a outra opção.
    • Prefira tf.nn.fused_batch_norm a tf.nn.batch_normalization.
    • Em tf.layers.batch_normalization, defina o argumento "fused" como "true".

tf.nn.depthwise_conv2d, tf.nn.separable_conv2d

  • Essas funções ainda não estão totalmente otimizadas e podem ter um desempenho pior do que uma convolução normal equivalente.

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.