Merge pull request #663 from karpathy/fix/reshuffle_zero_grad

Fix/reshuffle zero grad
This commit is contained in:
Andrej 2024-07-01 10:39:23 -07:00 committed by GitHub
commit 2e6a397d5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 16 additions and 17 deletions

View file

@ -61,7 +61,7 @@ int main(int argc, char *argv[]) {
// do a training step
gpt2_forward(&model, x, B, T);
gpt2_zero_grad(&model);
gpt2_backward_and_reduce(&model, x, y, 1, true);
gpt2_backward_and_reduce(&model, x, y, 1, 0);
float grad_norm = gpt2_calculate_grad_norm(&model, &multi_gpu_config);
float grad_scale = (grad_norm > 1.0f) ? 1.0f / grad_norm : 1.0f;
gpt2_update(&model, 1e-4f, 0.9f, 0.999f, 1e-8f, 0.0f, grad_scale, 1, &multi_gpu_config);

View file

@ -218,7 +218,7 @@ int main(int argc, char *argv[]) {
clock_gettime(CLOCK_MONOTONIC, &start);
gpt2_forward(&model, x, B, T);
gpt2_zero_grad(&model);
gpt2_backward_and_reduce(&model, x, y, 1, true);
gpt2_backward_and_reduce(&model, x, y, 1, 0);
clock_gettime(CLOCK_MONOTONIC, &end);
double time_elapsed_s = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
@ -336,7 +336,7 @@ int main(int argc, char *argv[]) {
dataloader_next_batch(&loader);
gpt2_forward(&model, loader.inputs, B, T);
gpt2_zero_grad(&model);
gpt2_backward_and_reduce(&model, loader.inputs, loader.targets, 1, true);
gpt2_backward_and_reduce(&model, loader.inputs, loader.targets, 1, 0);
gpt2_update(&model, 1e-4f, 0.9f, 0.95f, 1e-8f, 0.0f, 1.0f, step+11, &multi_gpu_config);
losses[step] = model.mean_loss;
tokens[step] = loader.inputs[0];
@ -351,7 +351,7 @@ int main(int argc, char *argv[]) {
dataloader_next_batch(&loader);
gpt2_forward(&model, loader.inputs, B, T);
gpt2_zero_grad(&model);
gpt2_backward_and_reduce(&model, loader.inputs, loader.targets, 1, true);
gpt2_backward_and_reduce(&model, loader.inputs, loader.targets, 1, 0);
gpt2_update(&model, 1e-4f, 0.9f, 0.95f, 1e-8f, 0.0f, 1.0f, step+11, &multi_gpu_config);
if(loader.inputs[0] != tokens[step]) {

View file

@ -740,10 +740,11 @@ float gpt2_validate(GPT2 *model, const int* inputs, const int* targets, size_t B
return mean_loss;
}
void gpt2_zero_grad(GPT2 *model) {
NVTX_RANGE_FN();
// the losses accumulate over the duration of gradient accumulation micro steps, also reset here
// there are currently two state vars during the gradient accumulation inner loop:
// 1) the losses accumulate += into acts.losses, reset here
// 2) the gradients accumulate += into grads_memory, reset here
cudaCheck(cudaMemset(model->acts.losses, 0, model->batch_size * model->seq_len * sizeof(float)));
if (model->grads_memory != NULL) {
cudaCheck(cudaMemset(model->grads_memory, 0, model->num_parameters * sizeof(floatX)));
@ -751,8 +752,14 @@ void gpt2_zero_grad(GPT2 *model) {
cudaCheck(cudaDeviceSynchronize());
}
void gpt2_backward_and_reduce(GPT2 *model, int* inputs, const int* targets, int grad_accum_steps, bool last_step) {
void gpt2_backward_and_reduce(GPT2 *model, int* inputs, const int* targets, int grad_accum_steps, int micro_step) {
NVTX_RANGE_FN();
bool last_step = micro_step == grad_accum_steps - 1;
// on the first micro-step zero the gradients, as we're about to += accumulate into them
if (micro_step == 0) {
gpt2_zero_grad(model);
}
// lazily allocate the memory for gradients of the weights and activations, if needed
if (model->grads_memory == NULL) {
@ -760,8 +767,6 @@ void gpt2_backward_and_reduce(GPT2 *model, int* inputs, const int* targets, int
// allocate buffers for weight gradients
printf0("allocating %d MiB for parameter gradients\n", (int)round(model->num_parameters * sizeof(floatX) / (1024 * 1024)));
model->grads_memory = malloc_and_point_parameters(&model->grads, model->param_elements, model->param_sizeof);
// init gradients of parameters and activations to zero
gpt2_zero_grad(model);
// initialise cpu scratch buffers for encoder backward
size_t num_c_groups = CEIL_DIV(model->config.channels, (WARP_SIZE * x128::size));
assert((size_t)(model->batch_size * model->seq_len) * num_c_groups < (1ULL<<31ULL)); // todo - maybe an issue for llama3-400B(?)
@ -1795,7 +1800,7 @@ int main(int argc, char *argv[]) {
// forward pass. note that we pass in grad_accum_steps, which scales down the loss
gpt2_forward(&model, train_loader.inputs, B, T);
// backward pass. all model params accumulate gradients with += inside this inner loop
gpt2_backward_and_reduce(&model, train_loader.inputs, train_loader.targets, grad_accum_steps, micro_step == grad_accum_steps - 1);
gpt2_backward_and_reduce(&model, train_loader.inputs, train_loader.targets, grad_accum_steps, micro_step);
}
float zloss = (float)(update_detector(&loss_outlier_detector, (double)model.mean_loss)); // loss z-score
// fetch the next learning rate
@ -1814,8 +1819,6 @@ int main(int argc, char *argv[]) {
float grad_scale = (grad_norm > grad_clip) ? grad_clip / grad_norm : 1.0f;
gpt2_update(&model, step_learning_rate, 0.9f, 0.95f, 1e-8f, weight_decay, grad_scale, step+1, &multi_gpu_config);
}
// zero out the gradients for the next iteration
gpt2_zero_grad(&model);
cudaCheck(cudaEventRecord(end));
cudaCheck(cudaEventSynchronize(end)); // wait for the end event to finish to get correct timings
// --------------- TRAINING SECTION END -------------------

View file

@ -698,10 +698,6 @@ if __name__ == "__main__":
write_state(model, x, y, logits, loss, f"gpt2_{model_size_str}_debug_state.bin")
# reset the train_loader for the optimization below
train_loader.reset()
# clear the grads here explicitly because otherwise we'd have a duplicate grad accumulation
# since in the training loop we do a backward() and then zero_grad() at the end of the loop
# this would cause an incorrect first training step
model.zero_grad()
# -------------------------------------------------------------------------
# main training loop
@ -794,6 +790,7 @@ if __name__ == "__main__":
# --------------- TRAINING SECTION BEGIN -----------------
model.train()
optimizer.zero_grad(set_to_none=True)
# if we are trying to overfit a single batch, we reset the loader here
if args.overfit_single_batch:
train_loader.reset()
@ -830,7 +827,6 @@ if __name__ == "__main__":
param_group['lr'] = lr
# step the optimizer
optimizer.step()
optimizer.zero_grad(set_to_none=True)
# --------------- TRAINING SECTION END -------------------
# everything that follows now is just diagnostics, prints, logging, etc.