Ferramentas de IA 101

Configurando Treinamento, Fine-Tuning e Inferência de LLMs com GPUs NVIDIA e CUDA

mm
Adicione Unite.AI às suas fontes preferidas no Google
Nvidia GPU in Ubuntu Basics of GPU Parallel Computing GPU Based LLM Training Machine

O campo da inteligência artificial (IA) testemunhou avanços notáveis nos últimos anos, e no coração disso está a poderosa combinação de unidades de processamento gráfico (GPUs) e plataforma de computação paralela.

Modelos como GPT, BERT, e mais recentemente Llama, Mistral são capazes de entender e gerar texto humano com fluência e coerência sem precedentes. No entanto, treinar esses modelos requer vastas quantidades de dados e recursos computacionais, tornando as GPUs e o CUDA ferramentas indispensáveis nessa empreitada.

Este guia abrangente o levará pelo processo de configuração de uma GPU NVIDIA (NVDA ) no Ubuntu, cobrindo a instalação de componentes de software essenciais, como o driver NVIDIA, CUDA Toolkit, cuDNN, PyTorch e mais.

O Surgimento de Frameworks de IA Acelerados por CUDA

A aprendizagem de máquina acelerada por GPU foi impulsionada pelo desenvolvimento de frameworks de IA populares que utilizam o CUDA para computação eficiente. Frameworks como TensorFlow, PyTorch e MXNet têm suporte integrado ao CUDA, permitindo a integração transparente da aceleração de GPU em pipelines de aprendizagem de máquina.

De acordo com o Estudo de Desempenho de Produtos de Aprendizagem de Máquina de Centro de Dados da NVIDIA, modelos de aprendizagem de máquina acelerados por CUDA podem alcançar até 100 vezes mais desempenho em comparação com implementações baseadas em CPU.

A tecnologia de Instância Múltipla de GPU (MIG) da NVIDIA, introduzida com a arquitetura Ampere, permite que um único GPU seja particionado em várias instâncias seguras, cada uma com seus próprios recursos dedicados. Essa funcionalidade permite a compartilhamento eficiente de recursos de GPU entre vários usuários ou cargas de trabalho, maximizando a utilização e reduzindo os custos gerais.

Acelerando a Inferência de LLM com NVIDIA TensorRT

Embora as GPUs tenham sido instrumentais no treinamento de LLMs, a inferência eficiente é igualmente crucial para implantar esses modelos em ambientes de produção. O NVIDIA TensorRT, um otimizador e tempo de execução de inferência de aprendizagem de máquina de alto desempenho, desempenha um papel vital na aceleração da inferência de LLM em GPUs habilitados para CUDA.

De acordo com as medições de desempenho da NVIDIA, o TensorRT pode fornecer até 8 vezes mais desempenho de inferência e 5 vezes menos custo total de propriedade em comparação com a inferência baseada em CPU para grandes modelos de linguagem como o GPT-3.

O compromisso da NVIDIA com as iniciativas de código aberto foi uma força motriz por trás da adoção generalizada do CUDA na comunidade de pesquisa de IA. Projetos como cuDNN, cuBLAS e NCCL estão disponíveis como bibliotecas de código aberto, permitindo que pesquisadores e desenvolvedores aproveitem todo o potencial do CUDA para suas necessidades de aprendizagem de máquina.

Instalação

Ao configurar o desenvolvimento de IA, usar os drivers e bibliotecas mais recentes nem sempre é a melhor escolha. Por exemplo, embora o driver NVIDIA mais recente (545.xx) suporte o CUDA 12.3, o PyTorch e outras bibliotecas podem não suportar ainda essa versão. Portanto, usaremos o driver de versão 535.146.02 com CUDA 12.2 para garantir a compatibilidade.

Etapa de Instalação

1. Instalar Driver NVIDIA

Primeiro, identifique o modelo da sua GPU. Para este guia, usamos a GPU NVIDIA. Visite a página de download de drivers da NVIDIA, selecione o driver apropriado para a sua GPU e anote a versão do driver.

Para verificar pacotes de GPU pré-construídos no Ubuntu, execute:


sudo ubuntu-drivers list --gpgpu

Reinicie o computador e verifique a instalação:


nvidia-smi

2. Instalar CUDA Toolkit

O CUDA Toolkit fornece o ambiente de desenvolvimento para criar aplicativos acelerados por GPU de alto desempenho.

Para uma configuração que não seja de LLM/aprendizagem de máquina, você pode usar:


sudo apt install nvidia-cuda-toolkit

<p>No entanto, para garantir a compatibilidade com BitsAndBytes, seguiremos estas etapas:</p>

[code language=&amp;quot;BASH&amp;quot;]

<p>git clone https://github.com/TimDettmers/bitsandbytes.git
cd bitsandbytes/
bash install_cuda.sh 122 ~/local 1</p>

Verifique a instalação:


~/local/cuda-12.2/bin/nvcc --version

Defina as variáveis de ambiente:


<p>export CUDA_HOME=/home/roguser/local/cuda-12.2/
export LD_LIBRARY_PATH=/home/roguser/local/cuda-12.2/lib64
export BNB_CUDA_VERSION=122
export CUDA_VERSION=122</p>

3. Instalar cuDNN

Baixe o pacote cuDNN do site de desenvolvedores da NVIDIA. Instale-o com:


<p>sudo apt install ./cudnn-local-repo-ubuntu2204-8.9.7.29_1.0-1_amd64.deb</p>

Siga as instruções para adicionar a chave:


<p>sudo cp /var/cudnn-local-repo-ubuntu2204-8.9.7.29/cudnn-local-08A7D361-keyring.gpg /usr/share/keyrings/</p>

Instale as bibliotecas cuDNN:


<p>sudo apt update
sudo apt install libcudnn8 libcudnn8-dev libcudnn8-samples</p>

4. Configurar Ambiente Virtual Python

O Ubuntu 22.04 vem com Python 3.10. Instale venv:


<p>sudo apt-get install python3-pip
sudo apt install python3.10-venv</p>

Crie e ative o ambiente virtual:


<p>cd
mkdir test-gpu
cd test-gpu
python3 -m venv venv
source venv/bin/activate</p>

5. Instalar BitsAndBytes a Partir do Código Fonte

Navegue até o diretório BitsAndBytes e construa a partir do código fonte:


<p>cd ~/bitsandbytes
CUDA_HOME=/home/roguser/local/cuda-12.2/ \
LD_LIBRARY_PATH=/home/roguser/local/cuda-12.2/lib64 \
BNB_CUDA_VERSION=122 \
CUDA_VERSION=122 \
make cuda12x</p>

<p>CUDA_HOME=/home/roguser/local/cuda-12.2/ \
LD_LIBRARY_PATH=/home/roguser/local/cuda-12.2/lib64 \
BNB_CUDA_VERSION=122 \
CUDA_VERSION=122 \
python setup.py install</p>

6. Instalar PyTorch

Instale o PyTorch com o seguinte comando:


<p>pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121</p>

7. Instalar Hugging e Transformers

Instale as bibliotecas transformers e accelerate:


<p>pip install transformers
pip install accelerate</p>

O Poder do Processamento Paralelo

No núcleo, as GPUs são processadores paralelos altamente projetados para lidar com milhares de threads concorrentes de forma eficiente. Essa arquitetura as torna adequadas para as tarefas computacionalmente intensivas envolvidas no treinamento de modelos de aprendizagem de máquina, incluindo LLMs. A plataforma CUDA, desenvolvida pela NVIDIA, fornece um ambiente de software que permite aos desenvolvedores aproveitar todo o potencial dessas GPUs, permitindo que eles escrevam código que possa aproveitar as capacidades de processamento paralelo do hardware.
Acelerando o treinamento de LLM com GPUs e CUDA.

O treinamento de grandes modelos de linguagem é uma tarefa computacionalmente exigente que requer o processamento de vastas quantidades de dados de texto e a realização de inúmeras operações matriciais. As GPUs, com seus milhares de núcleos e alta largura de banda de memória, são ideais para essas tarefas. Ao aproveitar o CUDA, os desenvolvedores podem otimizar seu código para aproveitar as capacidades de processamento paralelo das GPUs, reduzindo significativamente o tempo necessário para treinar LLMs.

Por exemplo, o treinamento do GPT-3, um dos maiores modelos de linguagem até o momento, foi possível graças ao uso de milhares de GPUs NVIDIA executando código otimizado para CUDA. Isso permitiu que o modelo fosse treinado em uma quantidade sem precedentes de dados, levando ao seu desempenho impressionante em tarefas de linguagem natural.


<p>import torch
import torch.nn as nn
import torch.optim as optim
from transformers import GPT2LMHeadModel, GPT2Tokenizer</p>

<p># Carregue o modelo GPT-2 pré-treinado e o tokenizer
model = GPT2LMHeadModel.from_pretrained('gpt2')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')</p>

<p># Mova o modelo para a GPU, se disponível
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)</p>

<p># Defina os dados de treinamento e os hiperparâmetros
train_data = [...] # Seus dados de treinamento
batch_size = 32
num_epochs = 10
learning_rate = 5e-5</p>

<p># Defina a função de perda e o otimizador
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)</p>

<p># Loop de treinamento
for epoch in range(num_epochs):
for i in range(0, len(train_data), batch_size):
# Prepare as sequências de entrada e saída
inputs, targets = train_data[i:i+batch_size]
inputs = tokenizer(inputs, return_tensors="pt", padding=True)
inputs = inputs.to(device)
targets = targets.to(device)</p>

<p># Passo para frente
outputs = model(**inputs, labels=targets)
loss = outputs.loss</p>

<p># Passo para trás e otimização
optimizer.zero_grad()
loss.backward()
optimizer.step()</p>

<p>print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item()}')</p>

Neste exemplo de código, demonstramos o treinamento de um modelo de linguagem GPT-2 usando PyTorch e GPUs habilitadas para CUDA. O modelo é carregado na GPU (se disponível), e o loop de treinamento aproveita o paralelismo das GPUs para realizar passos para frente e para trás de forma eficiente, acelerando o treinamento.

Bibliotecas de Aprendizagem de Máquina Aceleradas por CUDA

Além da própria plataforma CUDA, a NVIDIA e a comunidade de código aberto desenvolveram uma série de bibliotecas aceleradas por CUDA que permitem a implementação eficiente de modelos de aprendizagem de máquina, incluindo LLMs. Essas bibliotecas fornecem implementações otimizadas de operações comuns, como multiplicações de matrizes, convoluções e funções de ativação, permitindo que os desenvolvedores se concentrem na arquitetura do modelo e no processo de treinamento, em vez de otimização de baixo nível.

Uma dessas bibliotecas é a cuDNN (CUDA Deep Neural Network library), que fornece implementações altamente ajustadas de rotinas padrão usadas em redes neurais profundas. Ao aproveitar a cuDNN, os desenvolvedores podem acelerar significativamente o treinamento e a inferência de seus modelos, alcançando ganhos de desempenho de até várias ordens de magnitude em comparação com implementações baseadas em CPU.


<p>import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.cuda.amp import autocast</p>

<p>class ResidualBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(out_channels))</p>

<p>def forward(self, x):
with autocast():
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = F.relu(out)
return out</p>

Neste trecho de código, definimos um bloco residual para uma rede neural convolucional (CNN) usando PyTorch. O gerenciador de contexto autocast do PyTorch é usado para habilitar o treinamento de precisão mista, o que pode fornecer ganhos de desempenho significativos em GPUs habilitadas para CUDA, mantendo a alta precisão. A função F.relu é otimizada pela cuDNN, garantindo a execução eficiente em GPUs.

Treinamento Distribuído e Multi-GPU para Escalabilidade

À medida que os LLMs e os modelos de aprendizagem de máquina continuam a crescer em tamanho e complexidade, os requisitos computacionais para treinar esses modelos também aumentam. Para atender a esse desafio, os pesquisadores e desenvolvedores têm recorrido a técnicas de treinamento distribuído e multi-GPU, que permitem que eles aproveitem o processamento combinado de múltiplas GPUs em várias máquinas.

O CUDA e as bibliotecas associadas, como a NCCL (NVIDIA Collective Communications Library), fornecem primitivas de comunicação eficientes que permitem a transferência de dados e sincronização transparentes entre múltiplas GPUs, permitindo o treinamento distribuído em uma escala sem precedentes.

&amp;lt;/pre&amp;gt;
import torch.distributed as dist

<p>from torch.nn.parallel import DistributedDataParallel as DDP</p>

<p># Inicialize o treinamento distribuído
dist.init_process_group(backend='nccl', init_method='...')
local_rank = dist.get_rank()
torch.cuda.set_device(local_rank)</p>

<p># Crie o modelo e mova para a GPU
model = MyModel().cuda()</p>

<p># Envie o modelo com DDP
model = DDP(model, device_ids=[local_rank])</p>

<p># Loop de treinamento (distribuído)
for epoch in range(num_epochs):
for data in train_loader:
inputs, targets = data
inputs = inputs.cuda(non_blocking=True)
targets = targets.cuda(non_blocking=True)</p>

<p>outputs = model(inputs)
loss = criterion(outputs, targets)</p>

<p>optimizer.zero_grad()
loss.backward()
optimizer.step()</p>

Neste exemplo, demonstramos o treinamento distribuído usando o módulo DistributedDataParallel do PyTorch. O modelo é envolvido com DDP, que automaticamente lida com a parallelização de dados, sincronização de gradientes e comunicação entre múltiplas GPUs usando a NCCL. Essa abordagem permite a escalabilidade eficiente do processo de treinamento em várias máquinas, permitindo que os pesquisadores e desenvolvedores treinem modelos maiores e mais complexos em um tempo razoável.

Implantando Modelos de Aprendizagem de Máquina com CUDA

Embora as GPUs e o CUDA tenham sido principalmente usados para treinar modelos de aprendizagem de máquina, eles também são cruciais para a implantação eficiente e inferência. À medida que os modelos de aprendizagem de máquina se tornam cada vez mais complexos e intensivos em recursos, a aceleração de GPU é essencial para alcançar o desempenho em tempo real em ambientes de produção.

A NVIDIA TensorRT é um otimizador e tempo de execução de inferência de aprendizagem de máquina de alto desempenho que fornece baixa latência e alto throughput de inferência em GPUs habilitadas para CUDA. A TensorRT pode otimizar e acelerar modelos treinados em frameworks como TensorFlow, PyTorch e MXNet, permitindo a implantação eficiente em várias plataformas, desde sistemas incorporados até centros de dados.


import tensorrt as trt

<p># Carregue o modelo pré-treinado
model = load_model(...)</p>

<p># Crie o motor da TensorRT
logger = trt.Logger(trt.Logger.INFO)
builder = trt.Builder(logger)
network = builder.create_network()
parser = trt.OnnxParser(network, logger)</p>

<p># Analise e otimize o modelo
success = parser.parse_from_file(model_path)
engine = builder.build_cuda_engine(network)</p>

<p># Execute a inferência na GPU
context = engine.create_execution_context()
inputs, outputs, bindings, stream = allocate_buffers(engine)</p>

<p># Defina os dados de entrada e execute a inferência
set_input_data(inputs, input_data)
context.execute_async_v2(bindings=bindings, stream_handle=stream.ptr)</p>

# Processar a saída
# ...

Neste exemplo, demonstramos o uso da TensorRT para implantar um modelo de aprendizagem de máquina pré-treinado em uma GPU habilitada para CUDA. O modelo é primeiro analisado e otimizado pela TensorRT, que gera um motor de inferência altamente otimizado personalizado para o modelo e o hardware específicos. Esse motor pode então ser usado para realizar a inferência eficiente na GPU, aproveitando o CUDA para computação acelerada.

Conclusão

A combinação de GPUs e CUDA foi instrumental nos avanços em modelos de linguagem grande, visão computacional, reconhecimento de fala e vários outros domínios da aprendizagem de máquina. Ao aproveitar as capacidades de processamento paralelo das GPUs e as bibliotecas otimizadas fornecidas pelo CUDA, os pesquisadores e desenvolvedores podem treinar e implantar modelos cada vez mais complexos com alta eficiência.

À medida que o campo da IA continua a evoluir, a importância das GPUs e do CUDA só crescerá. Com hardware e otimizações de software ainda mais poderosos, podemos esperar ver avanços adicionais no desenvolvimento e implantação de sistemas de IA, empurrando os limites do que é possível.

Eu passei os últimos cinco anos me imergindo no fascinante mundo de Aprendizado de Máquina e Aprendizado Profundo. Minha paixão e expertise me levaram a contribuir para mais de 50 projetos de engenharia de software diversificados, com um foco particular em IA/ML. Minha curiosidade contínua também me levou em direção ao Processamento de Linguagem Natural, um campo que estou ansioso para explorar mais.