Desempenho do Modelo ChatGLM3-6B-32k na GPU RTX 4090D: Análise de Memória e Velocidade de Inferência

1. Visão Geral do Projeto

Este documento apresenta uma análise prática da implantação do modelo de linguagem ChatGLM3-6B-32k em uma placa de vídeo consumer-grade, a RTX 4090D. A solução é totalmente local, garantindo privacidade dos dados e eliminando a dependência de uma conexão com a internet para a inferência do modelo.

A abordagem utiliza o framework Streamlit para criar uma interface web interativa, permitindo um serviço de diálogo inteligente com desempenho otimizado. É uma configuração particularmente adequada para ambientes corporativos que tratam dados confidenciais ou para desenvolvedores que buscam uma experiência de baixa latência.

2. Especificações e Ambiente

2.1 Requisitos de Hardware

Os componentes mínimos e recomendados para uma operação estável são:

  • GPU: NVIDIA RTX 4090D (24GB VRAM)
  • Memória RAM do Sistema: 32GB ou superior
  • Armazenamento: Mínimo de 20GB em SSD para os pesos do modelo e ambiente.

2.2 Configuração do Ambiente de Software

Utilizamos um contêiner Docker para padronizar o ambiente. As versões das bibliotecas críticas são fixadas para evitar incompatibilidades.

# Base image com suporte a CUDA
FROM pytorch/pytorch:2.6.0-cuda12.1-cudnn8-runtime

# Instalação de dependências com versões específicas
RUN pip install transformers==4.40.2
RUN pip install streamlit==1.35.0
RUN pip install accelerate==0.30.1

O script para iniciar a aplicação Streamlit é simples:

# Executar a aplicação
streamlit run server.py --server.port 8501 --server.enableCORS false

3. Monitoramento do Consumo de Memória VRAM

3.1 Alocación Inicial do Modelo

O processo de carregar o modelo na memória da GPU segue um padrão previsível de consumo.

Estado VRAM Utilizada (Aprox.) Observação
Inicial (Sistema) 1.2 GB Overhead do driver e sistema.
Carregando Pesos Crescendo até 18 GB Pesos do modelo transferidos para a VRAM.
Modelo Pronto 19.5 GB estável Inclui pesos, buffers e espaço de trabalho.

Conclui-se que a placa de vídeo de 24GB mantém uma folga de aproximadamente 4.5GB, o que é suficiente para operações contínuas.

3.2 Variação Durante a Inferência

Uma operação de geração de texto causa um pico temporário na memória.

import torch
import gc

def obter_uso_vram_gb():
    if not torch.cuda.is_available():
        return 0.0
    torch.cuda.synchronize()
    mem_info = torch.cuda.mem_get_info()
    mem_usada_gb = (mem_info[1] - mem_info[0]) / (1024 ** 3)
    return round(mem_usada_gb, 2)

# Exemplo de uso
print(f"Uso antes da geração: {obter_uso_vram_gb()} GB")
# ... código de inferência do modelo ...
print(f"Uso pico: {obter_uso_vram_gb()} GB")
gc.collect()
torch.cuda.empty_cache()
print(f"Uso após limpeza: {obter_uso_vram_gb()} GB")

A análise mostra um acréscimo transitório de 0.2 a 0.5 GB por consulta. A memória é liberada após a conclusão, graças ao gerenciamento automático do PyTorch.

4. Benchmarks de Performance

4.1 Latência em Consultas Únicas

Os testes foram conduzidos com o comprimento de contexto de 32k tokens.

Tamanho da Entrada (palavras) Tempo até Primeiro Token (s) Tempo Total de Geração (s)
Curta (10-50) 0.8 - 1.2 2.5 - 4.0
Média (50-100) 1.2 - 1.8 3.5 - 5.5
Longa (100-200) 1.8 - 2.5 5.0 - 8.0

4.2 Teste de Carga Contínua

Para avaliar a estabilidade sob uso contínuo, simulamos uma sessão de diálogos múltiplos.

import time
from transformers import AutoTokenizer, AutoModel

nome_modelo = "THUDM/chatglm3-6b-32k"
tokenizer = AutoTokenizer.from_pretrained(nome_modelo, trust_remote_code=True)
model = AutoModel.from_pretrained(nome_modelo, trust_remote_code=True).half().cuda()

# Etapa de aquecimento (warm-up)
_, historico = model.chat(tokenizer, "Olá", history=[])

# Medição do throughput
tempos_turno = []
for i in range(15):
    inicio = time.perf_counter()
    _, historico = model.chat(tokenizer, f"Mensagem de teste {i}: explique o conceito de {i*10}.", history=historico)
    tempos_turno.append(time.perf_counter() - inicio)

media_tempo = sum(tempos_turno) / len(tempos_turno)
print(f"Tempo médio por turno em 15 iterações: {media_tempo:.2f}s")

Os resultados indicam um tempo médio por turno de aproximadamente 3.2 segundos, demonstrando que o sistema mantém um desempenho consistente em operações seqüenciais.

5. Otimizações com Streamlit

5.1 Gerenciamento Eficiente de Recursos

Uma das principais vantagens do Streamlit é o mecanismo de cache, que evita recarregamentos desencessários do modelo.

import streamlit as st
from transformers import AutoTokenizer, AutoModel

@st.cache_resource(show_spinner="Carregando modelo...")
def inicializar_componentes():
    """Carrega o tokenizer e o modelo uma única vez por sessão."""
    tk = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b-32k", trust_remote_code=True)
    mdl = AutoModel.from_pretrained("THUDM/chatglm3-6b-32k", trust_remote_code=True).half().cuda()
    return tk, mdl

# Uso na aplicação
tokenizer, model = inicializar_componentes()

Isso reduz drasticamente o tempo de carregamento inicial da aplicação para os usuários subsequentes.

5.2 Experiência de Saída em Fluxo

Para melhorar a percepção de velocidade, implementamos a geração de texto em tempo real (streaming).

def gerar_resposta_em_fluxo(prompt, historico_chat):
    """Gera a resposta do modelo token por token."""
    for chunk, novo_historico in model.stream_chat(tokenizer, prompt, historico_chat):
        yield chunk, novo_historico

# Integração na interface Streamlit
def main():
    # ... código da interface ...
    prompt_usuario = st.chat_input("Faça sua pergunta:")
    if prompt_usuario:
        with st.chat_message("assistant"):
            placeholder = st.empty()
            resposta_completa = ""
            # Atualiza a interface a cada novo token recebido
            for texto_parcial, _ in gerar_resposta_em_fluxo(prompt_usuario, historico_sessao):
                resposta_completa += texto_parcial
                placeholder.markdown(resposta_completa + "▌")
            placeholder.markdown(resposta_completa)

if __name__ == "__main__":
    main()

Essa técnica cria uma experiência mais dinâmica, similar a uma conversa em tempo real.

6. Casos de Uso Prático

O modelo demonstra utilidade em cenários específicos graças ao seu longo contexto.

  • Assistência ao Desenvolvimento: Capacidade de analisar fragmentos de código extensos, sugerir correções e explicar lógica complexa em múltiplas linguagens.
  • Processamento de Documentos: Realização de sumarização, extração de informações e respostas a perguntas específicas sobre textos longos, como relatórios técnicos ou artigos acadêmicos.

A performance se mantém útil mesmo para entradas que se aproximam do limite de 32 mil tokens de contexto.

Tags: ChatGLM3-6B RTX 4090D Streamlit inferência de modelos gerenciamento de memória VRAM

Publicado em 6-7 02:37 por Thomas