Quando usar o Dataflow para inferência de ML, recomendamos que use a transformação RunInference. A utilização desta transformação oferece várias vantagens, incluindo:
- Gestão inteligente da memória do modelo otimizada para um worker do Dataflow quando realiza a inferência local.
- O processamento em lote dinâmico, que usa caraterísticas do pipeline e restrições definidas pelo utilizador para otimizar o desempenho.
- Funcionalidades de back-end do Dataflow com reconhecimento de ML que podem oferecer um melhor débito e latência.
- Mecanismos de recuo inteligente e escalabilidade automática quando se depara com quotas de inferência remota.
- Métricas prontas para produção e funcionalidades operacionais.
Quando usar RunInference, existem vários aspetos a considerar:
Gestão de memória
Quando carrega um modelo de ML médio ou grande, a sua máquina pode ficar sem memória. O Dataflow fornece ferramentas para ajudar a evitar erros de falta de memória (OOM) ao carregar modelos de ML. Use a tabela seguinte para determinar a abordagem adequada para o seu cenário.
| Cenário | Solução |
|---|---|
| Os modelos são suficientemente pequenos para caberem na memória. |
Use a transformação RunInference sem configurações adicionais. A transformação RunInference partilha os modelos em vários
processos. Se conseguir ajustar um modelo por núcleo da CPU na sua máquina, então
o seu pipeline pode usar a configuração predefinida.
|
| Vários modelos com formações diferentes estão a realizar a mesma tarefa. | Use chaves por modelo. Para mais informações, consulte o artigo Execute a inferência de ML com vários modelos preparados de forma diferente. |
| Um modelo é carregado na memória e todos os processos partilham este modelo. |
Use o parâmetro Se estiver a criar um controlador de modelo personalizado, em vez de usar o parâmetro |
| Tem de configurar o número exato de modelos carregados na sua máquina. |
Para controlar exatamente quantos modelos são carregados, use o parâmetro
Se estiver a criar um controlador de modelos personalizado, substitua o parâmetro
|
Para mais informações sobre a gestão de memória com o Dataflow, consulte o artigo Resolva problemas de falta de memória do Dataflow.
Criar lotes
Existem muitas formas de fazer o processamento em lote no Beam, mas, quando realizar a inferência, recomendamos que deixe a transformação RunInference processar o lote. Se o seu modelo tiver o melhor desempenho com um tamanho do lote específico, considere restringir os parâmetros de tamanho do lote alvo de RunInference. A maioria dos controladores de modelos expõe os tamanhos máximos e mínimos dos lotes como parâmetros. Por exemplo, para controlar o tamanho do lote introduzido num pipeline do HuggingFace, pode definir o seguinte controlador de modelo:
mh = HuggingFacePipelineModelHandler('text-classification', min_batch_size=4, max_batch_size=16)
A transformação RunInference respeita sempre o tamanho máximo do lote. O tamanho mínimo do lote é um objetivo, mas não é garantido que seja respeitado em todos os casos. Por exemplo, consulte a secção Agrupamento baseado em pacotes abaixo.
Processamento em lote baseado em pacotes
O Dataflow passa dados para transformações em pacotes. Estes pacotes podem variar em tamanho consoante as heurísticas definidas pelo Dataflow. Normalmente, os pacotes em pipelines de processamento em lote são bastante grandes (O(100s) de elementos), enquanto para pipelines de streaming podem ser bastante pequenos (incluindo o tamanho 1).
Por predefinição, o RunInference gera lotes a partir de cada pacote e não
gera lotes entre pacotes. Isto significa que, se tiver um tamanho do lote mínimo de 8, mas apenas 3 elementos restantes no seu pacote, o RunInference usa um tamanho do lote de 3. A maioria dos controladores de modelos expõe um parâmetro max_batch_duration_secs que lhe permite substituir este comportamento. Se max_batch_duration_secs estiver definido, RunInference
processa em lote em vários pacotes. Se a transformação não conseguir atingir o tamanho do lote alvo com um único pacote, aguarda, no máximo, max_batch_duration_secs antes de gerar um lote. Por exemplo, para ativar o processamento em lote de vários pacotes quando usar um pipeline do HuggingFace, pode definir o seguinte controlador de modelos:
mh = HuggingFacePipelineModelHandler('text-classification', min_batch_size=4, max_batch_size=16, max_batch_duration_secs=3)
Esta funcionalidade é útil se tiver tamanhos de lotes muito baixos no seu pipeline. Caso contrário, o custo de sincronização para processar em lote em vários conjuntos de dados normalmente não compensa, porque pode causar uma mistura dispendiosa.
Processamento de falhas
A gestão de erros é uma parte importante de qualquer pipeline de produção. O Dataflow processa elementos em pacotes arbitrários e tenta novamente o pacote completo se ocorrer um erro para qualquer elemento nesse pacote. Se não aplicar processamento de erros adicional, o Dataflow tenta novamente os pacotes que incluem um item com falha quatro vezes quando executado no modo de lote. O pipeline falha completamente quando um único pacote falha quatro vezes. Quando é executado no modo de streaming, o Dataflow tenta novamente um pacote que inclui um item com falhas indefinidamente, o que pode fazer com que o pipeline fique permanentemente parado.
A RunInference oferece um mecanismo de processamento de erros integrado com a respetiva função with_exception_handling.
Quando aplica esta função, encaminha todas as falhas para um registo de falhas separado
PCollection juntamente com as respetivas mensagens de erro. Isto permite-lhe processá-los novamente. Se associar operações de pré-processamento ou pós-processamento ao controlador do modelo, o RunInference também encaminha essas operações para a recolha de falhas. Por exemplo, para recolher todas as falhas de um controlador de modelos com operações de pré-processamento e pós-processamento, use a seguinte lógica:
main, other = pcoll | RunInference(model_handler.with_preprocess_fn(f1).with_postprocess_fn(f2)).with_exception_handling()
# handles failed preprocess operations, indexed in the order in which they were applied
other.failed_preprocessing[0] | beam.Map(logging.info)
# handles failed inferences
other.failed_inferences | beam.Map(logging.info)
# handles failed postprocess operations, indexed in the order in which they were applied
other.failed_postprocessing[0] | beam.Map(logging.info)
Limites de tempo
Quando usa a funcionalidade with_exception_handling de RunInference, também pode definir um limite de tempo para cada operação, que é contabilizado por lote. Isto permite-lhe
evitar que uma única inferência bloqueada torne todo o pipeline não responsivo. Se ocorrer um
tempo limite, o registo com tempo limite é encaminhado para o erro PCollection, todo o
estado do modelo é limpo e recriado, e a execução normal continua.
# Timeout execution after 60 seconds
main, other = pcoll | RunInference(model_handler).with_exception_handling(timeout=60)
A partir do Beam 2.68.0, também pode especificar um limite de tempo através da opção de pipeline --element_processing_timeout_minutes. Neste caso, um limite de tempo faz com que um item de trabalho com falha seja repetido até ter êxito, em vez de encaminhar a inferência com falha para uma fila de mensagens rejeitadas.
Trabalhar com aceleradores
Quando usa aceleradores, muitos controladores de modelos têm configurações específicas do acelerador que pode ativar. Por exemplo, quando usar uma GPU e pipelines do HuggingFace, recomendamos que defina o parâmetro device como GPU:
mh = HuggingFacePipelineModelHandler('text-classification', device='GPU')
Também recomendamos que comece com uma única instância de VM e execute o pipeline localmente nessa instância. Para o fazer, siga os passos descritos no guia de resolução de problemas da GPU. Isto pode reduzir significativamente o tempo necessário para executar um pipeline. Esta abordagem também pode ajudar a compreender melhor o desempenho do seu trabalho.
Para mais informações sobre a utilização de aceleradores no Dataflow, consulte a documentação do Dataflow sobre GPUs e TPUs.
Gestão de dependências
Os pipelines de ML incluem frequentemente dependências grandes e importantes, como o PyTorch ou o TensorFlow. Para gerir estas dependências, recomendamos que use contentores personalizados quando implementar a sua tarefa em produção. Isto garante que a tarefa é executada num ambiente estável em várias execuções e simplifica a depuração.
Para mais informações sobre a gestão de dependências, consulte a página de gestão de dependências do Python do Beam.
O que se segue?
- Explore os blocos de notas de ML do Dataflow para ver exemplos práticos.
- Obtenha informações detalhadas sobre a utilização da AA com o Apache Beam na documentação de pipelines de AA/AM.
- Saiba mais acerca da
RunInferenceAPI. - Saiba mais sobre as métricas
que pode usar para monitorizar a sua transformação
RunInference. - Regresse à página Acerca da aprendizagem automática do Dataflow para ver uma vista geral das capacidades de aprendizagem automática do Dataflow.