SPB Git

spb/forge Public MIT

Forge — LLM training from scratch in pure C++20 + Metal on Apple Silicon.

C++ 61.2% C 23% Python 7.6% TeX 7.2% CMake 1.1%

Add elapsed_s column to log.csv for structured metrics consumers

Forge Studio (the GUI companion) tails log.csv as its metrics channel;
wall-clock elapsed enables its time-axis mode and honest ETA math.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed 5 days ago (Aug 5, 2026) parent 2e570b0

Showing 1 changed file with +6 and −3

modified src/train/trainer.cpp +6 −3
@@ -103,7 +103,8 @@ void Trainer::train(const std::string& resume_from) {
103 103 FILE* csv = std::fopen((out_dir_ + "/log.csv").c_str(),
104 104 start_step > 0 ? "ab" : "wb");
105 105 if (csv && start_step == 0)
106 std::fprintf(csv, "step,loss,lr,grad_norm,tokens_per_sec,val_loss\n");
106 + std::fprintf(csv, "step,loss,lr,grad_norm,tokens_per_sec,val_loss,elapsed_s\n");
107 + const auto run_t0 = std::chrono::steady_clock::now();
107 108
108 109 const int64_t min_lr_steps = tc.max_steps;
109 110 const float min_lr = tc.lr * tc.min_lr_ratio;
@@ -168,9 +169,11 @@ void Trainer::train(const std::string& resume_from) {
168 169 std::fflush(stdout);
169 170 }
170 171 if (csv) {
171 std::fprintf(csv, "%lld,%.6f,%.6e,%.6f,%.1f,%.6f\n",
172 + const double elapsed =
173 + std::chrono::duration<double>(t1 - run_t0).count();
174 + std::fprintf(csv, "%lld,%.6f,%.6e,%.6f,%.1f,%.6f,%.3f\n",
172 175 static_cast<long long>(step), loss_val, double(lr),
173 double(grad_norm), tps, double(val));
176 + double(grad_norm), tps, double(val), elapsed);
174 177 std::fflush(csv);
175 178 }
176 179
177 180