---------------------------------------------------------------------------- main training loop
| 650 | // ---------------------------------------------------------------------------- |
| 651 | // main training loop |
| 652 | int main() { |
| 653 | |
| 654 | setLogLevel(kWarn); |
| 655 | |
| 656 | printf("Creating GPU context\n"); |
| 657 | WGPURequiredLimits requiredLimits = LIMITS_BUFFER_SIZE_1GB; |
| 658 | gpu::Context ctx = gpu::createContext({}, {}, { |
| 659 | .requiredLimits = &requiredLimits |
| 660 | }); |
| 661 | // gpu::Context ctx = gpu::createContext(); |
| 662 | |
| 663 | // build the GPT-2 model from a checkpoint |
| 664 | GPT2 model; |
| 665 | gpt2_build_from_checkpoint(ctx, &model, "gpt2_124M.bin"); |
| 666 | |
| 667 | // build the DataLoaders from tokens files. for now use tiny_shakespeare if available, else tiny_stories |
| 668 | const char* tiny_stories_train = "dev/data/tinystories/TinyStories_train.bin"; |
| 669 | const char* tiny_stories_val = "dev/data/tinystories/TinyStories_val.bin"; |
| 670 | const char* tiny_shakespeare_train = "dev/data/tinyshakespeare/tiny_shakespeare_train.bin"; |
| 671 | const char* tiny_shakespeare_val = "dev/data/tinyshakespeare/tiny_shakespeare_val.bin"; |
| 672 | const char* train_tokens = access(tiny_shakespeare_train, F_OK) != -1 ? tiny_shakespeare_train : tiny_stories_train; |
| 673 | const char* val_tokens = access(tiny_shakespeare_val, F_OK) != -1 ? tiny_shakespeare_val : tiny_stories_val; |
| 674 | constexpr int B = 4; // batch size 4 (i.e. 4 independent token sequences will be trained on) |
| 675 | constexpr int T = 64; // sequence length 64 (i.e. each sequence is 64 tokens long). must be <= maxT, which is 1024 for GPT-2 |
| 676 | DataLoader train_loader, val_loader; |
| 677 | dataloader_init(&train_loader, train_tokens, B, T, 0, 1, 1); |
| 678 | dataloader_init(&val_loader, val_tokens, B, T, 0, 1, 0); |
| 679 | printf("train dataset num_batches: %zu\n", train_loader.num_tokens / (B*T)); |
| 680 | printf("val dataset num_batches: %zu\n", val_loader.num_tokens / (B*T)); |
| 681 | int val_num_batches = 5; |
| 682 | |
| 683 | // build the Tokenizer |
| 684 | Tokenizer tokenizer; |
| 685 | tokenizer_init(&tokenizer, "gpt2_tokenizer.bin"); |
| 686 | |
| 687 | // some memory for generating samples from the model |
| 688 | uint64_t rng_state = 1337; |
| 689 | int* gen_tokens = (int*)mallocCheck(B * T * sizeof(int)); |
| 690 | const int genT = 64; // number of steps of inference we will do |
| 691 | |
| 692 | |
| 693 | // train |
| 694 | struct timespec start, end; |
| 695 | printf("Starting training\n"); |
| 696 | for (int step = 0; step <= 40; step++) { |
| 697 | printf("Step %d\n", step); |
| 698 | |
| 699 | // once in a while estimate the validation loss |
| 700 | if (step % 10 == 0) { |
| 701 | float val_loss = 0.0f; |
| 702 | dataloader_reset(&val_loader); |
| 703 | for (int i = 0; i < val_num_batches; i++) { |
| 704 | dataloader_next_batch(&val_loader); |
| 705 | gpt2_forward(ctx, &model, val_loader.inputs, val_loader.targets, B, T); |
| 706 | val_loss += model.mean_loss; |
| 707 | } |
| 708 | val_loss /= val_num_batches; |
| 709 | printf("val loss %f\n", val_loss); |
nothing calls this directly
no test coverage detected