Práticas recomendadas: inferência de IA no Cloud Run com GPUs

Esta página fornece práticas recomendadas para otimizar o desempenho ao usar um serviço do Cloud Run com uma GPU para inferência de IA, com foco em modelos de linguagem grandes (LLMs).

Você precisa criar e implantar um serviço do Cloud Run capaz de responder em tempo real para escalonar eventos. Isso significa que você precisa:

  • Use modelos que carregam rápido e exigem uma transformação mínima em estruturas prontas para GPU e otimize como elas são carregadas.
  • Usem configurações que permitem execução máxima, eficiente e simultânea para reduzir o número de GPUs necessárias para atender consultas de destino por segundo (QPS) mantendo os custos baixos.

Maneiras recomendadas de carregar modelos de ML grandes no Cloud Run

O Google recomenda armazenar modelos de ML dentro de imagens de contêiner. ou otimizar carregá-los do Cloud Storage.

Compensações entre armazenar e carregar modelos

Confira uma comparação das opções:

Local do modelo Hora da implantação Experiência de desenvolvimento Tempo de inicialização do contêiner Custo de armazenamento
Imagem do contêiner Lento. Uma imagem que contém um modelo grande vai demorar mais para ser importada para o Cloud Run. As mudanças na imagem do contêiner exigirão uma nova implantação, que pode ser lenta para imagens grandes. Depende do tamanho do modelo. Para modelos muito grandes, use o Cloud Storage para ter um desempenho mais previsível, porém mais lento. Possivelmente várias cópias no Artifact Registry.
Cloud Storage, carregado usando a montagem de volume do Cloud Storage FUSE Rápido. Modelo baixado durante a inicialização do contêiner. Não é difícil de configurar e não requer mudanças na imagem Docker. Rápido quando há otimizações de rede. Não carrega o download em paralelo. Uma cópia no Cloud Storage.
Cloud Storage, baixado simultaneamente usando o comando de CLI do Google Cloud gcloud storage cp ou a API de Cloud Storage conforme mostrado no exemplo de código de download simultâneo do gerente de transferência. Rápido. Modelo baixado durante a inicialização do contêiner. Um pouco mais difícil de configurar porque será preciso instalar a CLI do Google Cloud na imagem ou atualizar o código do aplicativo para usar a API Cloud Storage. Rápido quando há otimizações de rede. A CLI do Google Cloud faz o download do arquivo modelo em paralelo, o que é mais rápido do que a montagem do FUSE. Uma cópia no Cloud Storage.
Internet Rápido. Modelo baixado durante a inicialização do contêiner. Geralmente mais simples (muitos frameworks fazem o download de modelos de repositórios centrais). Geralmente ruim e imprevisível:
  • Os frameworks podem aplicar transformações de modelo durante a inicialização. (Faça isso no tempo de build.)
  • O host do modelo e as bibliotecas para baixar o modelo podem não ser eficientes.
  • Há um risco de confiabilidade associado ao download na Internet. Seu serviço pode não ser iniciado se o destino de download estiver inativo, e o modelo subjacente baixado pode mudar, o que diminui a qualidade. Recomendamos que você hospede em seu próprio bucket do Cloud Storage.
Depende do provedor de hospedagem do modelo.

Armazenar modelos em imagens de contêiner

Benefícios do armazenamento de modelos de ML em imagens de contêiner implantadas no Cloud Run das otimizações integradas de streaming de imagens de contêineres do Cloud Run, o que maximiza o tempo de carregamento do arquivo sem outras otimizações de rede.

A criação de contêineres que incluem modelos de ML pode levar algum tempo. Se você estiver usando o Cloud Build, poderá configurá-lo para usar máquinas maiores e ter builds mais rápidos. Para fazer isso, crie uma imagem usando um arquivo de configuração de build com estas etapas:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'IMAGE', '.']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'IMAGE']
images:
- IMAGE
options:
 machineType: 'E2_HIGHCPU_32'
 diskSizeGb: '500'
 

Pode criar uma cópia de modelo por imagem se a camada que contém o modelo for distinta entre as imagens (hash diferente). Pode haver custo de Artifact Registry adicional porque pode haver uma cópia do modelo por imagem se a camada de modelo for única em cada imagem.

Armazenar modelos no Cloud Storage

Para otimizar o carregamento de modelos de ML do Cloud Storage, usando montagens de volume do Cloud Storage ou diretamente a API do Cloud Storage ou a linha de comando, é necessário usar a VPC direta com o valor de configuração de saída definido como all-traffic, junto com o Private Service Connect.

Carregar modelos da Internet

Para otimizar o carregamento do modelo de ML pela Internet, roteie todo o tráfego pela rede VPC com o valor de configuração de saída definido como all-traffic e configure o Cloud NAT para acessar a Internet pública com alta largura de banda.

Considerações sobre criação, implantação, ambiente de execução e design do sistema

As seções a seguir descrevem considerações sobre build, implantação, ambiente de execução e design do sistema.

No tempo de build

A lista a seguir mostra as considerações que você precisa levar em conta ao planejar seu build:

  • Escolha uma boa imagem de base. Comece com uma imagem dos contêineres de aprendizado profundo ou do registro de contêineres da NVIDIA para o framework de ML que você está usando. Essas imagens têm os pacotes mais recentes relacionados ao desempenho instalados. Não recomendamos criar uma imagem personalizada.
  • Escolha modelos quantizados de 4 bits para maximizar a simultaneidade, a menos que você prove que eles afetam a qualidade dos resultados. A quantização produz modelos menores e mais rápidos, reduzindo a quantidade de memória de GPU necessária para fornecer o modelo e pode aumentar o paralelismo no ambiente de execução. O ideal é que os modelos sejam treinados na profundidade de bits de destino, em vez de quantizados para ela.
  • Escolha um formato de modelo com tempos de carregamento rápidos para minimizar o tempo de inicialização do contêiner, como o GGUF. Esses formatos refletem com mais precisão o tipo de quantização desejada e exigem menos transformações quando carregados na GPU. Por motivos de segurança, não use checkpoints no formato pickle.
  • Crie e aqueça caches do LLM no tempo de build. Inicie o LLM na máquina de build enquanto cria a imagem Docker. Ative o armazenamento em cache de comandos e o feed comum ou comandos de exemplo para ajudar no armazenamento em cache para uso no mundo real. Salve as saídas que são geradas para que sejam carregadas no ambiente de execução.
  • Salve seu próprio modelo de inferência gerado durante o tempo de build. Isso poupa tempo significativo em comparação ao carregamento de modelos armazenados de forma menos eficiente e aplicação de transformações como quantização na inicialização do contêiner.

Na implantação

  1. Certifique-se de definir a simultaneidade de serviço com precisão no Cloud Run.
  2. Ajuste suas sondagens de inicialização com base na sua configuração.

As sondagens de inicialização determinam se o contêiner foi iniciado e está pronto para aceitar o tráfego. Considere estes pontos importantes ao configurar sondagens de inicialização:

  • Tempo de inicialização adequado: aguarde o tempo suficiente para que o contêiner, incluindo os modelos, seja totalmente inicializado e carregado.
  • Verificação de prontidão do modelo: configure a sondagem para ser aprovada somente quando o aplicativo estiver pronto para atender às solicitações. A maioria dos mecanismos de veiculação consegue isso automaticamente quando o modelo é carregado na memória da GPU, evitando solicitações prematuras.

Observe que o Ollama pode abrir uma porta TCP antes do carregamento de um modelo. Para solucionar isso:

  • Pré-carregar modelos: consulte a documentação do Ollama para orientação sobre como pré-carregar seu modelo durante a inicialização.

No ambiente de execução

  • Gerencie ativamente o tamanho de contexto compatível. Quanto menor for a janela de contexto com suporte, mais consultas poderão ser executadas em paralelo. Detalhes de como fazer isso dependem da estrutura.
  • Use os caches do LLM gerados no tempo de build. Forneça as mesmas flags usadas no tempo de build ao gerar o comando e o cache de prefixo.
  • Carregar do modelo salvo que você acabou de gravar. Consulte Compensações de armazenamento e carregamento de modelos para obter uma comparação sobre como carregar o modelo.
  • Considere usar um cache de chave-valor quantizado se o framework oferecer suporte. Isso pode reduzir os requisitos de memória por consulta e permitir a configuração de mais paralelismo. No entanto, isso também pode afetar a qualidade.
  • Ajuste a quantidade de memória da GPU a ser reservada para pesos de modelo, ativações e caches de chave-valor. Defina o valor mais alto possível sem receber um erro de falta de memória.
  • Configure sua simultaneidade corretamente no código de serviço. Verifique se seu código do serviço está configurado para funcionar com suas configurações de simultaneidade do serviço do Cloud Run.
  • Verifique se o framework tem alguma opção para melhorar o desempenho da inicialização do contêiner (por exemplo, usando o carregamento em paralelo de modelos).

No nível de design do sistema

  • Adicione caches semânticos onde apropriado. Em alguns casos, o armazenamento em cache de consultas e respostas inteiras pode ser uma ótima maneira de limitar o custo de consultas comuns.
  • Controle a variância nos preâmbulos. Os caches de comando são úteis apenas quando contêm os comandos em sequência. Caches são efetivamente prefixos em cache. Inserções ou edições na sequência significam que elas não estão em cache ou apenas estão parcialmente presentes.

Escalonamento automático e GPUs

O Cloud Run escalona automaticamente o número de instâncias de cada revisão com base em fatores como a utilização da CPU e a simultaneidade de solicitações. No entanto, o Cloud Run não escalona automaticamente o número de instâncias com base no uso da GPU.

Para uma revisão com uma GPU, se a revisão não tiver uso significativo da CPU, o Cloud Run vai escalonar horizontalmente para a simultaneidade de solicitações. Para alcançar o escalonamento ideal para simultaneidade de solicitação, você deve definir um máximo de solicitações simultâneas por instância, conforme descrito na próxima seção.

Máximo de solicitações simultâneas por instância

A configuração de máximo de solicitações simultâneas por instância controla o número máximo de solicitações que o Cloud Run envia para uma única instância de uma só vez. Você deve ajustar a simultaneidade para corresponder à simultaneidade máxima que o código em cada instância pode processar com bom desempenho.

Simultaneidade máxima e cargas de trabalho de IA

Ao executar uma carga de trabalho de inferência de IA em uma GPU em cada instância, a máxima simultaneidade que o código pode processar com bom desempenho depende de framework específico e detalhes de implementação. A ação a seguir afeta a maneira como você define o máximo ideal de configuração de solicitações simultâneas:

  • Número de instâncias de modelo carregadas na GPU
  • Número de consultas paralelas por modelo
  • Uso de lotes
  • Parâmetros específicos de configuração de lote
  • Quantidade de trabalho sem GPU

Se o máximo de solicitações simultâneas for definido como muito alto, as solicitações podem terminar aguardando dentro da instância pelo acesso à GPU, o que leva a um aumento da latência. Se o máximo de solicitações simultâneas for definido como muito baixo, a GPU poderá estar subutilizada fazendo com que o Cloud Run escalone horizontalmente mais instâncias do que o necessário.

Uma regra prática para configurar o máximo de solicitações simultâneas para as cargas de trabalho de IA é:

(Number of model instances * parallel queries per model) + (number of model instances * ideal batch size)

Por exemplo, suponha que uma instância carregue instâncias de modelo 3 na GPU e cada instância de modelo possa processar consultas paralelas 4. O tamanho ideal do lote também é 4, porque esse é o número de consultas paralelas que cada instância de modelo pode processar. Usando a regra geral, você definiria o máximo de solicitações simultâneas 24: (3 * 4) + (3 * 4).

Observe que essa fórmula é apenas uma regra prática. A configuração do máximo ideal de solicitações simultâneas depende dos detalhes específicos da sua implementação. Para alcançar seu desempenho ideal real, recomendamos testar a carga do seu serviço com diferentes configurações de solicitações simultâneas máximas para avaliar qual opção tem melhor desempenho.

Compensações entre capacidade de processamento, latência e custo

Consulte Compensações entre capacidade de processamento, latência e custo para o impacto de solicitações simultâneas máximas na capacidade de processamento, na latência e no custo. Observe que todos serviços Cloud Run que usam as GPUs possuem CPU sempre alocadas.