Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions megatron/training.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def pretrain(train_valid_test_dataset_provider,
# Model, optimizer, and learning rate.
timers('model-and-optimizer-setup').start()
model, optimizer, lr_scheduler = setup_model_and_optimizer(model_provider)
args.parameters_in_billions_no_embedding = get_parameters_in_billions(model, exclude_embeddings=True)
print_rank_0(f'estimated model parameters: {get_parameters_in_billions(model)}')
print_rank_0(f'estimated model parameters without embeddings: {get_parameters_in_billions(model, exclude_embeddings=True)}')
timers('model-and-optimizer-setup').stop()
Expand Down Expand Up @@ -661,6 +662,26 @@ def add_to_logging(name):
if iteration % args.log_interval == 0:
elapsed_time = timers('interval-time').elapsed()
elapsed_time_per_iteration = elapsed_time / total_iterations

seq_len = args.curriculum_seqlen if args.curriculum_learning else args.seq_length

# throughput
samples_per_sec = batch_size / (elapsed_time_per_iteration * 1e3)
samples_per_sec_per_replica = samples_per_sec / args.data_parallel_size
tokens_per_sec = samples_per_sec * seq_len
tokens_per_sec_per_replica = tokens_per_sec / args.data_parallel_size

# general TFLOPs formula
# model_size_in_B * 4 * 2 * seqlen * global_batch_size / (time_in_sec_per_interation * total_gpus * 1e3)
#
# The factor of 4 is when used with activation check-pointing,
# otherwise it will be 3, but for 200B model, activation check-pointing will always be on.
#
# here:
# model_size_in_B * 4 * 2 * seqlen * batch_size / (time_in_msec_per_interation * total_gpus)
checkpoint_activations_factor = 4 if args.checkpoint_activations else 3
tflops = args.parameters_in_billions_no_embedding * checkpoint_activations_factor * 2 * seq_len * batch_size / (elapsed_time_per_iteration * args.world_size)

# only the last rank process has a non-None _GLOBAL_TENSORBOARD_WRITER
if writer and is_last_rank():
if args.log_timers_to_tensorboard:
Expand All @@ -670,6 +691,17 @@ def add_to_logging(name):
elapsed_time_per_iteration, args.consumed_train_samples)
writer.add_scalar('iteration-time/iteration-time vs tokens',

@thomasw21 thomasw21 Nov 29, 2021

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove this one then as it doesn't make sense IMO, nor does the iteration-time/iteration-time vs samples. I think this just prints out how much time it took to run a step at a specific token timestamp.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this metric differ from tokens/samples per second?

@stas00 stas00 Nov 29, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, other than being the inverse, it's different while the batch size is changing.

samples_per_sec = batch_size / (elapsed_time_per_iteration * 1e3)

elapsed_time_per_iteration, args.consumed_train_tokens)
writer.add_scalar('iteration-time/samples per second',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a better metric would be to print out tokens per second? Typically samples per second is complicated with CL (samples change in terms of size).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually isn't that just the inverse of what we'd expect in iteration-time/iteration-time vs samples?

@VictorSanh VictorSanh Nov 29, 2021

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can have both. tokens per second is likely going to be impacted by CL anyway (shorter sequences)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually isn't that just the inverse of what we'd expect in iteration-time/iteration-time vs samples?

It isn't while bs is ramping up:

samples_per_sec = batch_size / (elapsed_time_per_iteration * 1e3)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added:

  • tokens per second
  • tokens per second per replica

can remove the 2 samples per sec entries if wanted.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sorry it's not the inverse right now. But I would have expected iteration-time vs samples to return the time it took to process a single sample, which is the inverse of the number of samples you process per second.

IMO, iteration-time vs samples doesn't bring much information besides it increases linearly during batch size rampup and then stays relatively constant. We should already see those behaviours in batch-size/batch-size vs samples. Though sometimes we notice bad allocations where the iteration time doubles (https://huggingface.co/bigscience/tr7c-1B3-alibi-logs/tensorboard) but we should be able to see the same thing with the new logs X per second.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, a lot of graphs are redundant in the TBs. It doesn't cost much to log (time and disk space) so I am not worried about information that can be inferred from another logging

samples_per_sec, args.iteration)
writer.add_scalar('iteration-time/samples per second per replica',
samples_per_sec_per_replica, args.iteration)
writer.add_scalar('iteration-time/tokens per second',
tokens_per_sec, args.iteration)
writer.add_scalar('iteration-time/tokens per second per replica',
tokens_per_sec_per_replica, args.iteration)
writer.add_scalar('iteration-time/TFLOPs per gpu (estimated)',
tflops, args.iteration)

log_string = ' iteration {:8d}/{:8d} |'.format(
iteration, args.train_iters)
log_string += ' consumed samples: {:12d} |'.format(
Expand Down Expand Up @@ -701,6 +733,8 @@ def add_to_logging(name):
total_loss_dict[skipped_iters_key])
log_string += ' number of nan iterations: {:3d} |'.format(
total_loss_dict[nan_iters_key])
log_string += ' samples per second: {:.3f} |'.format(samples_per_sec)
log_string += ' TFLOPs: {:.2f} |'.format(tflops)
total_loss_dict[advanced_iters_key] = 0
total_loss_dict[skipped_iters_key] = 0
total_loss_dict[nan_iters_key] = 0
Expand Down