Entre em contato

Configurando treinamento, ajuste fino e inferência de LLMs com GPUs NVIDIA e CUDA

Ferramentas de IA 101

Configurando treinamento, ajuste fino e inferência de LLMs com GPUs NVIDIA e CUDA

mm
Nvidia GPU no Ubuntu Noções básicas de GPU Parallel Computing Máquina de treinamento LLM baseada em GPU

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

Modelos como GPT, BERTe mais recentemente lhama, Mistral são capazes de compreender e gerar textos semelhantes aos humanos com fluência e coerência sem precedentes. Porém, treinar esses modelos requer grandes quantidades de dados e recursos computacionais, tornando GPUs e CUDA ferramentas indispensáveis ​​nessa empreitada.

Este guia completo orientará você no processo de configuração de uma GPU NVIDIA no Ubuntu, cobrindo a instalação de componentes de software essenciais, como o driver NVIDIA, CUDA Toolkit, cuDNN, PyTorch e muito mais.

A ascensão das estruturas de IA aceleradas por CUDA

O aprendizado profundo acelerado por GPU foi alimentado pelo desenvolvimento de estruturas populares de IA que aproveitam CUDA para computação eficiente. Estruturas como TensorFlow, PyTorch e MXNet têm suporte integrado para CUDA, permitindo integração perfeita da aceleração de GPU em pipelines de aprendizado profundo.

De acordo com o eBook da Digibee Estudo de desempenho de produto de aprendizagem profunda de data center NVIDIA, os modelos de aprendizagem profunda acelerados por CUDA podem atingir um desempenho até 100 vezes mais rápido em comparação com implementações baseadas em CPU.

A tecnologia de GPU Multi-Instância (MIG) da NVIDIA, introduzida com a arquitetura Ampere, permite que uma única GPU seja particionada em várias instâncias seguras, cada uma com seus próprios recursos dedicados. Esse recurso permite o 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 LLM com NVIDIA TensorRT

Embora as GPUs tenham sido fundamentais no treinamento de LLMs, a inferência eficiente é igualmente crucial para a implantação desses modelos em ambientes de produção. NVIDIA TensorRT, um otimizador de inferência e tempo de execução de aprendizado profundo de alto desempenho, desempenha um papel vital na aceleração da inferência LLM em GPUs habilitadas para CUDA.

De acordo com os benchmarks da NVIDIA, o TensorRT pode fornecer desempenho de inferência até 8x mais rápido e custo total de propriedade 5x menor em comparação à inferência baseada em CPU para grandes modelos de linguagem como GPT-3.

O compromisso da NVIDIA com iniciativas de código aberto tem sido uma força motriz por trás da ampla adoção 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 seu aprendizado profundo.

Instalação

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

Passos da instalação

1. Instale o driver NVIDIA

Primeiro, identifique seu modelo de GPU. Para este guia, usamos a GPU NVIDIA. Visite a Página de download do driver NVIDIA, selecione o driver apropriado para 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 seu computador e verifique a instalação:

nvidia-smi

2. Instale o kit de ferramentas CUDA

O CUDA Toolkit fornece o ambiente de desenvolvimento para a criação de aplicativos acelerados por GPU de alto desempenho.

Para uma configuração não LLM/aprendizado profundo, você pode usar:

sudo apt install nvidia-cuda-toolkit

However, to ensure compatibility with BitsAndBytes, we will follow these steps:

[code language="BASH"]

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

Verifique a instalação:

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

Defina as variáveis ​​de ambiente:

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

3. Instale o cuDNN

Faça o download do pacote cuDNN do Site do desenvolvedor NVIDIA. Instale-o com:

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

Siga as instruções para adicionar o chaveiro:

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

Instale as bibliotecas cuDNN:

sudo apt update
sudo apt install libcudnn8 libcudnn8-dev libcudnn8-samples

4. Configure o ambiente virtual Python

Ubuntu 22.04 vem com Python 3.10. Instale o venv:

sudo apt-get install python3-pip
sudo apt install python3.10-venv

Crie e ative o ambiente virtual:

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

5. Instale BitsAndBytes da fonte

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

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

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

6. Instale o PyTorch

Instale o PyTorch com o seguinte comando:

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

7. Instale Abraços e Transformadores

Instale os transformadores e acelere as bibliotecas:

pip install transformers
pip install accelerate

O poder do processamento paralelo

Em sua essência, as GPUs são processadores altamente paralelos projetados para lidar com milhares de threads simultâneos com eficiência. Essa arquitetura os torna adequados para as tarefas computacionalmente intensivas envolvidas no treinamento de modelos de aprendizagem profunda, incluindo LLMs. A plataforma CUDA, desenvolvida pela NVIDIA, fornece um ambiente de software que permite aos desenvolvedores aproveitar todo o potencial dessas GPUs, permitindo-lhes escrever código que possa aproveitar os recursos de processamento paralelo do hardware.
Acelerando LLM Treinamento com GPUs e CUDA.

O treinamento de grandes modelos de linguagem é uma tarefa computacionalmente exigente que requer o processamento de grandes quantidades de dados de texto e a execuçã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 vantagens dos recursos de processamento paralelo das GPUs, reduzindo significativamente o tempo necessário para treinar LLMs.

Por exemplo, a formação de 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. Isto permitiu que o modelo fosse treinado em uma quantidade de dados sem precedentes, levando ao seu desempenho impressionante em tarefas de linguagem natural.

import torch
import torch.nn as nn
import torch.optim as optim
from transformers import GPT2LMHeadModel, GPT2Tokenizer

# Load pre-trained GPT-2 model and tokenizer
model = GPT2LMHeadModel.from_pretrained('gpt2')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')

# Move model to GPU if available
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)

# Define training data and hyperparameters
train_data = [...] # Your training data
batch_size = 32
num_epochs = 10
learning_rate = 5e-5

# Define loss function and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# Training loop
for epoch in range(num_epochs):
for i in range(0, len(train_data), batch_size):
# Prepare input and target sequences
inputs, targets = train_data[i:i+batch_size]
inputs = tokenizer(inputs, return_tensors="pt", padding=True)
inputs = inputs.to(device)
targets = targets.to(device)

# Forward pass
outputs = model(**inputs, labels=targets)
loss = outputs.loss

# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()

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

Neste trecho de código de exemplo, demonstramos o treinamento de um GPT-2 modelo de linguagem 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 passes eficientes para frente e para trás, acelerando o processo de treinamento.

Bibliotecas aceleradas por CUDA para aprendizado profundo

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 profunda, 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 na otimização de baixo nível.

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

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.cuda.amp import autocast

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))

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

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

Treinamento distribuído e multi-GPU para escalabilidade

À medida que os LLMs e os modelos de aprendizagem profunda continuam a crescer em tamanho e complexidade, os requisitos computacionais para treinar esses modelos também aumentam. Para enfrentar esse desafio, pesquisadores e desenvolvedores recorreram a técnicas de treinamento distribuído e multi-GPU, que lhes permitem aproveitar o poder de processamento combinado de várias GPUs em várias máquinas.

CUDA e bibliotecas associadas, como NCCL (NVIDIA Collective Communications Library), fornecem primitivas de comunicação eficientes que permitem transferência e sincronização de dados contínuas entre várias GPUs, permitindo treinamento distribuído em uma escala sem precedentes.

</pre>
import torch.distributed as dist

from torch.nn.parallel import DistributedDataParallel as DDP

# Initialize distributed training
dist.init_process_group(backend='nccl', init_method='...')
local_rank = dist.get_rank()
torch.cuda.set_device(local_rank)

# Create model and move to GPU
model = MyModel().cuda()

# Wrap model with DDP
model = DDP(model, device_ids=[local_rank])

# Training loop (distributed)
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)

outputs = model(inputs)
loss = criterion(outputs, targets)

optimizer.zero_grad()
loss.backward()
optimizer.step()

Neste exemplo, demonstramos o treinamento distribuído usando o módulo DistributedDataParallel (DDP) do PyTorch. O modelo é encapsulado em DDP, que gerencia automaticamente o paralelismo de dados, a sincronização de gradiente e a comunicação entre múltiplas GPUs usando NCCL. Essa abordagem permite o escalonamento eficiente do processo de treinamento entre múltiplas máquinas, permitindo que pesquisadores e desenvolvedores treinem modelos maiores e mais complexos em um tempo razoável.

Implantando modelos de aprendizado profundo com CUDA

Embora GPUs e CUDA tenham sido usados ​​principalmente para treinar modelos de aprendizagem profunda, eles também são cruciais para implantação e inferência eficientes. À medida que os modelos de aprendizagem profunda se tornam cada vez mais complexos e consomem muitos recursos, a aceleração da GPU é essencial para alcançando desempenho em tempo real em ambientes de produção.

O TensorRT da NVIDIA é um otimizador de inferência de aprendizado profundo de alto desempenho e tempo de execução que fornece baixa latência e alto rendimento inferência em GPUs habilitadas para CUDA. O TensorRT pode otimizar e acelerar modelos treinados em estruturas como TensorFlow, PyTorch e MXNet, permitindo implantação eficiente em diversas plataformas, de sistemas embarcados a data centers.

import tensorrt as trt

# Load pre-trained model
model = load_model(...)

# Create TensorRT engine
logger = trt.Logger(trt.Logger.INFO)
builder = trt.Builder(logger)
network = builder.create_network()
parser = trt.OnnxParser(network, logger)

# Parse and optimize model
success = parser.parse_from_file(model_path)
engine = builder.build_cuda_engine(network)

# Run inference on GPU
context = engine.create_execution_context()
inputs, outputs, bindings, stream = allocate_buffers(engine)

# Set input data and run inference
set_input_data(inputs, input_data)
context.execute_async_v2(bindings=bindings, stream_handle=stream.ptr)

# Process output
# ...

Neste exemplo, demonstramos o uso do TensorRT para implantar um modelo de aprendizado profundo pré-treinado em uma GPU habilitada para CUDA. O modelo é primeiro analisado e otimizado pelo TensorRT, que gera um mecanismo de inferência altamente otimizado e adaptado para o modelo e hardware específicos. Esse mecanismo pode então ser usado para realizar inferências eficientes na GPU, aproveitando CUDA para computação acelerada.

Conclusão

A combinação de GPUs e CUDA tem sido fundamental para impulsionar os avanços em grandes modelos de linguagem, visão computacional, reconhecimento de fala e vários outros domínios de aprendizagem profunda. Ao aproveitar os recursos de processamento paralelo das GPUs e das bibliotecas otimizadas fornecidas pelo CUDA, 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ó aumentará. Com otimizações de hardware e software ainda mais poderosas, podemos esperar novos avanços no desenvolvimento e implantação de sistemas de IA, ultrapassando os limites do que é possível.

Passei os últimos cinco anos mergulhando no fascinante mundo do Machine Learning e Deep Learning. Minha paixão e experiência me levaram a contribuir para mais de 50 projetos diversos de engenharia de software, com foco particular em AI/ML. Minha curiosidade contínua também me atraiu para o Processamento de Linguagem Natural, um campo que estou ansioso para explorar mais.