Dezesseis Dias de Computação em Uma GPU
Uma Única Execução Longa
ANDREA-120M leva ~23 dias em uma RTX 4090 (FP16, 6 passos/min, 200K passos). Consumo de energia da parede, pânicos de kernel, travamentos de proxy, & mudanças deliberadas de configuração todos acontecem ao longo dessa janela. Sem checkpoints, um único contratempo descarta toda a execução.
v1 perdeu 27K passos por um erro (lr=0.001 agressivo demais) porque nenhum checkpoint estava mais próximo que o ponto de lançamento. v2 absorveu essa lição: cadência de checkpoint caiu para a cada 100 passos, & um manipulador de sinal CUDA garante uma escrita de checkpoint em SIGTERM.
Três Papéis
Um checkpoint serve três funções ao mesmo tempo:
1. Ponto de recuperação. Processo morre, máquina reinicia, pânico no kernel: retome do último step_NNNNNN.bin.
2. Pivô polido. Passo 112.619: mude o currículo sem retrainar. SIGUSR1 força um checkpoint limpo, o proxy para, novos caps & floors são enviados, CUDA retoma do ponto salvo sob uma nova política.
3. Fork de auditoria. Compare duas configurações nos mesmos pesos iniciais: copie um checkpoint, execute duas branches divergentes para frente, observe qual converge.
A cada 100 passos, temos ~17 minutos de treinamento entre as escritas a 6 passos/min. 100 passos também correspondem a sample_every: cada checkpoint corresponde a uma auditoria de amostra fresca, & cada auditoria de amostra corresponde a um ponto recuperável.
Três Funções para Um Arquivo
Cinco Regiões em Um Arquivo
O Formato
Cada step_NNNNNN.bin empacota cinco regiões contíguas:
[int32 step] [int32 n_params] [n_params x float32 weights] [n_params x float32 m] [n_params x float32 v]
Região por Região
Cabeçalho (8 bytes no total). Um número de passo de 32 bits nos diz onde neste snapshot de treinamento esta está; uma contagem de parâmetros de 32 bits nos diz quão grandes são os três arrays subsequentes.
Pesos (n_params x 4 bytes). Todo parâmetro aprendido, achatado. A ordem corresponde ao iterador de parâmetros do modelo: embeddings de token & posição, depois pesos de atenção & MLP por camada, depois a cabeça de saída.
Primeiro momento Adam m (n_params x 4 bytes). EMA de gradientes passados (beta1 = 0.9). Mesma forma que os pesos. Necessário para retomada do AdamW.
Segundo momento de Adam v (n_params x 4 bytes). EMA de gradientes quadrados passados (beta2 = 0.999). Mesmo formato que os pesos. Necessário para retomada do AdamW.
Tamanho Total
Total de bytes = 8 + 12 x n_params. ANDREA-12M (12.8M params): 154 MB em disco (147 MB arredondado). ANDREA-120M (~120M params) FP32: ~1.44 GB. Três arrays de formato idêntico, empilhados um após o outro, com um pequeno cabeçalho.
Por que Salvar m & v
Adam vanilla rastreia taxas de aprendizado por parâmetro via m & v. Dropar eles na escrita do checkpoint & uma execução retomada começa com momento zero & estimativa de variância zero, equivalente a taxa de aprendizado 0 por um passo então uma rampa súbita. Picos de perda; o modelo pode sair da sua bacia atual. Salvar m & v torna a retomada bit-equivalente (modulo aleatoriedade do dataloader) à baseline nunca-parada.
Dimensionando Um Checkpoint
SIGTERM & SIGUSR1
Por Que o CUDA Lida com Sinais
O treinamento executa como um processo em foreground de longa duração. Quando o proxy ou operador deseja que a GPU pare, um sinal é enviado para o engine CUDA. Sem um manipulador, o SIGTERM padrão mata o processo imediatamente: computação de gradiente em voo descartada, pesos mais recentes desde o último checkpoint perdidos. Com um manipulador, o engine escreve um checkpoint primeiro e depois sai de forma limpa.
SIGTERM: escrever & sair
Enviado por um botão de parada, um systemctl stop, ou um kill de um proxy pai. CUDA finaliza o passo atual, escreve step_NNNNNN.bin no disco, então sai. A recuperação deste estado precisa apenas do último .bin: zero trabalho perdido além do passo parcial em voo.
SIGUSR1: escrever & continuar
Enviado sob demanda por um operador ou script proxy. CUDA finaliza o passo atual, escreve step_NNNNNN.bin, então continua o treinamento como se nada tivesse acontecido. Útil para: acionar um ponto de auditoria logo antes de uma mudança de configuração; capturar pesos em um momento conhecido como bom; alinhar um checkpoint com uma execução de avaliação de qualidade de amostra externa.
A Sequência de Pivô Polonês (etapa 112,619)
1. O operador envia SIGUSR1 para o CUDA. O checkpoint é escrito na próxima fronteira de 100 etapas (etapa 112,700).
2. O operador para o proxy.
3. .samples.json & .state.json são arquivados (log de amostras & estado do bandit preservados como registro histórico).
4. .loss.json permanece no lugar. Histórico cumulativo de treinamento; nunca arquivado.
5. O proxy reinicia com novos caps & floors.
6. O CUDA retoma a partir de step_112700.bin com um bandit novo, mas pesos completos, m & v.
O histórico de perda continua ininterrupto através do pivot. O log de amostra reseta de forma limpa. O Bandit ganha um novo começo sob a nova política.
Escolhendo o Sinal
Histórico Cumulativo de Treinamento
Três Arquivos Sidecar
Ao lado de cada checkpoint, o proxy mantém três sidecars JSON no diretório de execução:
- .loss.json -- uma entrada por passo, sempre. ~200.000 entradas no final da execução. Histórico cumulativo de treinamento.
- .samples.json -- amostras geradas recentes para auditoria. Resetado em pivôs de polimento.
- .state.json -- puxões de braço do bandit, recompensas EMA, contadores de fase. Resetado em pivôs de polimento.
O Que é Resetado, O Que Persiste
Os pivôs poloneses são mudanças de política, não resets de execução. Os pesos do modelo, m, v e histórico de perda continuam ininterruptos. As recompensas acumuladas do bandit NÃO continuam: os novos limites superiores e inferiores definem uma política diferente, e o bandit deve reaprender sob a nova política a partir de um estado limpo.
Por que .loss.json Permanece
O histórico de perda serve como trilha de auditoria da execução. Toda reivindicação publicada sobre ANDREA-120M (EMA de perda no passo 110K, recuperação do pivô polonês, convergência no passo 112K) remete a entradas neste arquivo. Arquivar .loss.json entre fases forçaria os leitores a costurar fragmentos para reconstruir a execução; mantê-lo apenas em apêndice e intocado preserva a proveniência.
A Lição do Braço Zumbi
O passo 112,619 encontrou um braço repo-docstrings em .state.json carregando peso 1.546 de uma execução anterior. O estado do bandit havia sido preservado através de um reinício anterior, mas a fonte de dados não estava mais disponível, produzindo puxões zumbis que distorceram a contabilidade de exploração. Lição: o estado do bandit É permitido derivar através de reinícios de maneiras surpreendentes. O histórico de perda é o único arquivo que deve permanecer intocado pela vida inteira da execução.
Uma Regra para Governá-las Todas
Arquive .samples.json & .state.json livremente entre fases. Nunca arquive .loss.json. O .loss.json mais recente é sempre o histórico de treinamento canônico.
Aplicando a Regra
O Que Foi Construído & Por Quê
Cinco Decisões
1. Cadência: a cada 100 passos. Granularidade do ponto de recuperação ~17 minutos. Alinhado com sample_every para que cada checkpoint corresponda a uma auditoria de amostra fresca.
2. Formato: cabeçalho + 3 arrays. Mínimo: cabeçalho de 8 bytes nos diz o tamanho de cada array seguinte. Sem inchaço de metadados. Retomadas bit-equivalentes quando m & v são salvos.
3. Sinais: SIGTERM & SIGUSR1. Dois papéis, dois sinais. Desligamento padrão do systemd obtém um checkpoint limpo via SIGTERM; pontos de auditoria sob demanda obtêm um checkpoint limpo via SIGUSR1 sem parar.
4. Continuidade de perda: nunca arquivada. Histórico cumulativo de treinamento persiste através de pivôs de polimento, reinicializações & mudanças de política. Uma trilha de auditoria para toda a execução.
5. Estado do Bandit: resets permitidos. Política do Bandit vive sob uma configuração por vez. Pivôs de polimento resetam; histórico de perda continua. Duas vidas diferentes compartilham o mesmo diretório de execução.
O Que Esta Lição Conecta
- Atividade 23 (grow_a_language_model_sample_audit). cadência sample_every corresponde à cadência de checkpoint; ambas disparam a cada 100 passos.
- Atividade 24 (grow_a_language_model_microgpt_to_andrea). colapso v1, patch v2.5, pivô de polimento v3 todos requerem checkpoints limpos para operar.
- Atividade 10 (grow_a_language_model_adamw). Salvar m & v no checkpoint importa porque a regra de atualização do AdamW depende de ambos. Removê-los & retomar diverge.
Uma Última Verdade de Engenharia
Código sobrevive aos autores. Infraestrutura sobrevive aos construtores. Um formato simples de checkpoint sobrevive a todo esquema sofisticado de retomada que prometeu pular a salvação do estado do otimizador. Economize os bytes; economize a execução.