#include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #else #include #include #include #include #endif #ifdef _OPENMP #include #endif #pragma pack(push, 1) typedef struct { char magic[4]; // "NANO" uint32_t version; // 1 (untied) or 2 (tied) uint32_t header_size; // 64 int n_layer; int n_head; int n_embd; int block_size; int vocab_size; char padding[32]; } ModelHeader; #pragma pack(pop) typedef struct { int n_layer; int n_head; int n_embd; int block_size; int vocab_size; } Config; typedef struct { float* wte; float* wpe; float** ln1_w; float** ln1_b; float** c_attn_w; float** c_attn_b; float** c_proj_w; float** c_proj_b; float** ln2_w; float** ln2_b; float** fc_w; float** fc_b; float** mlp_proj_w; float** mlp_proj_b; float* ln_f_w; float* ln_f_b; float* lm_head_w; } Weights; typedef struct { float* k_cache; float* v_cache; } KVCache; static Config cfg; static Weights W; static float* model_data_buffer = NULL; // Operation profiling accumulators (microseconds) static long long prof_attn_us = 0; static long long prof_mlp_us = 0; static long long prof_lmhead_us = 0; static long long prof_sample_us = 0; void print_mem_stage(const char* stage) { #ifdef _WIN32 PROCESS_MEMORY_COUNTERS_EX pmc; if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) { double ws_mb = (double)pmc.WorkingSetSize / (1024.0 * 1024.0); double priv_mb = (double)pmc.PrivateUsage / (1024.0 * 1024.0); double shared_ws_mb = ws_mb > priv_mb ? (ws_mb - priv_mb) : 0.0; fprintf(stderr, "STAGE_MEM: stage=%-28s ws_mb=%7.2f priv_mb=%7.2f shared_mb=%7.2f\n", stage, ws_mb, priv_mb, shared_ws_mb); fflush(stderr); } #else FILE* f = fopen("/proc/self/statm", "r"); if (f) { long total_pages = 0, resident_pages = 0, shared_pages = 0; if (fscanf(f, "%ld %ld %ld", &total_pages, &resident_pages, &shared_pages) == 3) { long page_size = sysconf(_SC_PAGESIZE); double ws_mb = (double)(resident_pages * page_size) / (1024.0 * 1024.0); double shared_mb = (double)(shared_pages * page_size) / (1024.0 * 1024.0); double priv_mb = ws_mb > shared_mb ? (ws_mb - shared_mb) : 0.0; fprintf(stderr, "STAGE_MEM: stage=%-28s ws_mb=%7.2f priv_mb=%7.2f shared_mb=%7.2f\n", stage, ws_mb, priv_mb, shared_mb); fflush(stderr); } fclose(f); } #endif } static void layer_norm(float* out, const float* x, const float* w, const float* b, int size) { float mean = 0.0f, var = 0.0f; for (int i = 0; i < size; i++) mean += x[i]; mean /= size; for (int i = 0; i < size; i++) { float d = x[i] - mean; var += d * d; } var /= size; float scale = 1.0f / sqrtf(var + 1e-5f); for (int i = 0; i < size; i++) out[i] = (x[i] - mean) * scale * w[i] + b[i]; } static void matmul_vec(float* out, const float* mat, const float* x, int M, int K) { #pragma omp parallel for for (int i = 0; i < M; i++) { const float* row = mat + (long long)i * K; __m256 sum_vec = _mm256_setzero_ps(); int j = 0; for (; j <= K - 8; j += 8) { __m256 m_val = _mm256_loadu_ps(&row[j]); __m256 x_val = _mm256_loadu_ps(&x[j]); sum_vec = _mm256_fmadd_ps(m_val, x_val, sum_vec); } float sum_arr[8]; _mm256_storeu_ps(sum_arr, sum_vec); float sum = sum_arr[0] + sum_arr[1] + sum_arr[2] + sum_arr[3] + sum_arr[4] + sum_arr[5] + sum_arr[6] + sum_arr[7]; for (; j < K; j++) { sum += row[j] * x[j]; } out[i] = sum; } } static void add_bias(float* x, const float* b, int N) { #pragma omp parallel for for (int i = 0; i < N; i++) x[i] += b[i]; } static void residual_add(float* x, const float* y, int N) { #pragma omp parallel for for (int i = 0; i < N; i++) x[i] += y[i]; } static void gelu_inplace(float* x, int N) { const float c = 0.7978845608f; #pragma omp parallel for for (int i = 0; i < N; i++) { float v = x[i]; float t = tanhf(c * (v + 0.044715f * v * v * v)); x[i] = 0.5f * v * (1.0f + t); } } static void softmax_inplace(float* x, int N) { float max_val = x[0]; for (int i = 1; i < N; i++) if (x[i] > max_val) max_val = x[i]; float sum = 0.0f; for (int i = 0; i < N; i++) { x[i] = expf(x[i] - max_val); sum += x[i]; } for (int i = 0; i < N; i++) x[i] /= sum; } static void forward( int token_id, int pos, KVCache* kv, float* x, float* buf, float* qkv_buf, float* attn_buf, float* ff_buf, float* logits, bool profile_ops = false ) { const int C = cfg.n_embd; const int H = cfg.n_head; const int hs = C / H; float* content_row = W.wte + (long long)token_id * C; float* pos_row = W.wpe + (long long)pos * C; #pragma omp parallel for for (int i = 0; i < C; i++) x[i] = content_row[i] + pos_row[i]; for (int l = 0; l < cfg.n_layer; l++) { auto t_attn_start = std::chrono::high_resolution_clock::now(); layer_norm(buf, x, W.ln1_w[l], W.ln1_b[l], C); matmul_vec(qkv_buf, W.c_attn_w[l], buf, 3 * C, C); add_bias(qkv_buf, W.c_attn_b[l], 3 * C); float* q = qkv_buf; float* k = qkv_buf + C; float* v = qkv_buf + 2 * C; float* k_cache = kv->k_cache + (long long)l * cfg.block_size * C; float* v_cache = kv->v_cache + (long long)l * cfg.block_size * C; memcpy(k_cache + (long long)pos * C, k, C * sizeof(float)); memcpy(v_cache + (long long)pos * C, v, C * sizeof(float)); #pragma omp parallel for for (int h = 0; h < H; h++) { float* q_h = q + h * hs; float scale = 1.0f / sqrtf((float)hs); float* local_attn = attn_buf + h * cfg.block_size; for (int t = 0; t <= pos; t++) { float* k_h = k_cache + (long long)t * C + h * hs; float dot = 0.0f; for (int d = 0; d < hs; d++) dot += q_h[d] * k_h[d]; local_attn[t] = dot * scale; } softmax_inplace(local_attn, pos + 1); float* out_h = buf + h * hs; memset(out_h, 0, hs * sizeof(float)); for (int t = 0; t <= pos; t++) { float* v_h = v_cache + (long long)t * C + h * hs; float a = local_attn[t]; for (int d = 0; d < hs; d++) out_h[d] += a * v_h[d]; } } float* attn_out = qkv_buf; matmul_vec(attn_out, W.c_proj_w[l], buf, C, C); add_bias(attn_out, W.c_proj_b[l], C); residual_add(x, attn_out, C); if (profile_ops) { auto t_attn_end = std::chrono::high_resolution_clock::now(); prof_attn_us += std::chrono::duration_cast(t_attn_end - t_attn_start).count(); } auto t_mlp_start = std::chrono::high_resolution_clock::now(); layer_norm(buf, x, W.ln2_w[l], W.ln2_b[l], C); matmul_vec(ff_buf, W.fc_w[l], buf, 4 * C, C); add_bias(ff_buf, W.fc_b[l], 4 * C); gelu_inplace(ff_buf, 4 * C); matmul_vec(buf, W.mlp_proj_w[l], ff_buf, C, 4 * C); add_bias(buf, W.mlp_proj_b[l], C); residual_add(x, buf, C); if (profile_ops) { auto t_mlp_end = std::chrono::high_resolution_clock::now(); prof_mlp_us += std::chrono::duration_cast(t_mlp_end - t_mlp_start).count(); } } auto t_lm_start = std::chrono::high_resolution_clock::now(); layer_norm(buf, x, W.ln_f_w, W.ln_f_b, C); matmul_vec(logits, W.lm_head_w, buf, cfg.vocab_size, C); if (profile_ops) { auto t_lm_end = std::chrono::high_resolution_clock::now(); prof_lmhead_us += std::chrono::duration_cast(t_lm_end - t_lm_start).count(); } } static void map_weights(float* data, int version) { float* ptr = data; const int C = cfg.n_embd; const int L = cfg.n_layer; W.wte = ptr; ptr += (long long)cfg.vocab_size * C; W.wpe = ptr; ptr += (long long)cfg.block_size * C; W.ln1_w = (float**)malloc(L * sizeof(float*)); W.ln1_b = (float**)malloc(L * sizeof(float*)); W.c_attn_w = (float**)malloc(L * sizeof(float*)); W.c_attn_b = (float**)malloc(L * sizeof(float*)); W.c_proj_w = (float**)malloc(L * sizeof(float*)); W.c_proj_b = (float**)malloc(L * sizeof(float*)); W.ln2_w = (float**)malloc(L * sizeof(float*)); W.ln2_b = (float**)malloc(L * sizeof(float*)); W.fc_w = (float**)malloc(L * sizeof(float*)); W.fc_b = (float**)malloc(L * sizeof(float*)); W.mlp_proj_w = (float**)malloc(L * sizeof(float*)); W.mlp_proj_b = (float**)malloc(L * sizeof(float*)); for (int l = 0; l < L; l++) { W.ln1_w[l] = ptr; ptr += C; W.ln1_b[l] = ptr; ptr += C; W.c_attn_w[l] = ptr; ptr += 3LL * C * C; W.c_attn_b[l] = ptr; ptr += 3LL * C; W.c_proj_w[l] = ptr; ptr += 1LL * C * C; W.c_proj_b[l] = ptr; ptr += C; W.ln2_w[l] = ptr; ptr += C; W.ln2_b[l] = ptr; ptr += C; W.fc_w[l] = ptr; ptr += 4LL * C * C; W.fc_b[l] = ptr; ptr += 4LL * C; W.mlp_proj_w[l] = ptr; ptr += 1LL * C * 4 * C; W.mlp_proj_b[l] = ptr; ptr += C; } W.ln_f_w = ptr; ptr += C; W.ln_f_b = ptr; ptr += C; if (version == 2) { // Tied weights: lm_head shares wte buffer W.lm_head_w = W.wte; } else { // Untied weights: separate lm_head block W.lm_head_w = ptr; ptr += (long long)cfg.vocab_size * C; } // Print per-tensor table fprintf(stderr, "\n--- WEIGHT TENSOR LAYOUT TABLE (Format v%d) ---\n", version); fprintf(stderr, "%-26s | %10s | %10s | %12s | %5s\n", "Tensor", "Elements", "Size (MiB)", "File Offset", "Align"); fprintf(stderr, "----------------------------------------------------------------------\n"); auto row = [](const char* name, long long elems, void* p) { double mib = (double)(elems * sizeof(float)) / (1024.0 * 1024.0); uintptr_t offset = (uintptr_t)p - (uintptr_t)model_data_buffer + 64; uintptr_t align = (uintptr_t)p % 64; fprintf(stderr, "%-26s | %10lld | %10.2f | %12llu | %5llu\n", name, elems, mib, (unsigned long long)offset, (unsigned long long)align); }; row("wte", (long long)cfg.vocab_size * C, W.wte); row("wpe", (long long)cfg.block_size * C, W.wpe); for (int l = 0; l < L; l++) { char n[64]; snprintf(n, sizeof(n), "h.%d.ln1_w", l); row(n, C, W.ln1_w[l]); snprintf(n, sizeof(n), "h.%d.ln1_b", l); row(n, C, W.ln1_b[l]); snprintf(n, sizeof(n), "h.%d.c_attn_w", l); row(n, 3LL * C * C, W.c_attn_w[l]); snprintf(n, sizeof(n), "h.%d.c_attn_b", l); row(n, 3LL * C, W.c_attn_b[l]); snprintf(n, sizeof(n), "h.%d.c_proj_w", l); row(n, 1LL * C * C, W.c_proj_w[l]); snprintf(n, sizeof(n), "h.%d.c_proj_b", l); row(n, C, W.c_proj_b[l]); snprintf(n, sizeof(n), "h.%d.ln2_w", l); row(n, C, W.ln2_w[l]); snprintf(n, sizeof(n), "h.%d.ln2_b", l); row(n, C, W.ln2_b[l]); snprintf(n, sizeof(n), "h.%d.fc_w", l); row(n, 4LL * C * C, W.fc_w[l]); snprintf(n, sizeof(n), "h.%d.fc_b", l); row(n, 4LL * C, W.fc_b[l]); snprintf(n, sizeof(n), "h.%d.mlp_proj_w", l); row(n, 1LL * C * 4 * C, W.mlp_proj_w[l]); snprintf(n, sizeof(n), "h.%d.mlp_proj_b", l); row(n, C, W.mlp_proj_b[l]); } row("ln_f_w", C, W.ln_f_w); row("ln_f_b", C, W.ln_f_b); if (version == 2) { row("lm_head_w (TIED->wte)", (long long)cfg.vocab_size * C, W.lm_head_w); } else { row("lm_head_w (UNTIED)", (long long)cfg.vocab_size * C, W.lm_head_w); } fprintf(stderr, "----------------------------------------------------------------------\n\n"); // Assert and verify 64-byte alignment for all weight tensors int total_tensors = 0; int aligned_tensors = 0; auto check_ptr = [&](const char* name, void* p) { total_tensors++; uintptr_t addr = (uintptr_t)p; uintptr_t rem = addr % 64; if (rem == 0) aligned_tensors++; #ifndef NO_ALIGN_ASSERT if (rem != 0) { fprintf(stderr, "FATAL: Tensor %s at %p is NOT 64-byte aligned (offset %% 64 = %llu)!\n", name, p, (unsigned long long)rem); abort(); } #endif }; check_ptr("wte", W.wte); check_ptr("wpe", W.wpe); for (int l = 0; l < L; l++) { char name[64]; snprintf(name, sizeof(name), "h.%d.ln1_w", l); check_ptr(name, W.ln1_w[l]); snprintf(name, sizeof(name), "h.%d.ln1_b", l); check_ptr(name, W.ln1_b[l]); snprintf(name, sizeof(name), "h.%d.c_attn_w", l); check_ptr(name, W.c_attn_w[l]); snprintf(name, sizeof(name), "h.%d.c_attn_b", l); check_ptr(name, W.c_attn_b[l]); snprintf(name, sizeof(name), "h.%d.c_proj_w", l); check_ptr(name, W.c_proj_w[l]); snprintf(name, sizeof(name), "h.%d.c_proj_b", l); check_ptr(name, W.c_proj_b[l]); snprintf(name, sizeof(name), "h.%d.ln2_w", l); check_ptr(name, W.ln2_w[l]); snprintf(name, sizeof(name), "h.%d.ln2_b", l); check_ptr(name, W.ln2_b[l]); snprintf(name, sizeof(name), "h.%d.fc_w", l); check_ptr(name, W.fc_w[l]); snprintf(name, sizeof(name), "h.%d.fc_b", l); check_ptr(name, W.fc_b[l]); snprintf(name, sizeof(name), "h.%d.mlp_proj_w", l); check_ptr(name, W.mlp_proj_w[l]); snprintf(name, sizeof(name), "h.%d.mlp_proj_b", l); check_ptr(name, W.mlp_proj_b[l]); } check_ptr("ln_f_w", W.ln_f_w); check_ptr("ln_f_b", W.ln_f_b); check_ptr("lm_head_w", W.lm_head_w); fprintf(stderr, "ALIGN_ASSERT: %d/%d weight tensors verified 64-byte aligned (ptr %% 64 == 0)\n", aligned_tensors, total_tensors); } int main(int argc, char* argv[]) { print_mem_stage("process_start"); auto start_time = std::chrono::high_resolution_clock::now(); bool dump_logits = false; const char* model_path = "model.bin"; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--dump-logits") == 0) dump_logits = true; if (strcmp(argv[i], "--model") == 0 && i + 1 < argc) model_path = argv[++i]; } #ifdef _WIN32 HANDLE hFile = CreateFileA(model_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "ERROR_MODEL_NOT_FOUND: could not open %s\n", model_path); return 1; } ModelHeader header; DWORD bytesRead = 0; if (!ReadFile(hFile, &header, sizeof(ModelHeader), &bytesRead, NULL) || bytesRead != sizeof(ModelHeader)) { fprintf(stderr, "ERROR: Failed to read model header\n"); CloseHandle(hFile); return 1; } if (memcmp(header.magic, "NANO", 4) != 0) { if (*(int*)header.magic == 8) { fprintf(stderr, "ERROR: Legacy model format detected (20-byte unaligned header). Expected magic 'NANO' (64-byte aligned header). Model rejected.\n"); } else { fprintf(stderr, "ERROR: Invalid model format. Expected magic 'NANO', got 0x%08X. Model rejected.\n", *(uint32_t*)header.magic); } CloseHandle(hFile); return 1; } if (header.version != 1 && header.version != 2) { fprintf(stderr, "ERROR: Unsupported model version %u. Expected version 1 or 2.\n", header.version); CloseHandle(hFile); return 1; } if (header.header_size != 64) { fprintf(stderr, "ERROR: Unsupported header size %u. Expected 64 bytes.\n", header.header_size); CloseHandle(hFile); return 1; } cfg.n_layer = header.n_layer; cfg.n_head = header.n_head; cfg.n_embd = header.n_embd; cfg.block_size = header.block_size; cfg.vocab_size = header.vocab_size; HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL); void* mapped_data = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); if (!mapped_data) { fprintf(stderr, "ERROR: MapViewOfFile failed\n"); CloseHandle(hMap); CloseHandle(hFile); return 1; } model_data_buffer = (float*)((char*)mapped_data + 64); #else int fd = open(model_path, O_RDONLY); if (fd < 0) { fprintf(stderr, "ERROR_MODEL_NOT_FOUND: could not open %s\n", model_path); return 1; } struct stat sb; if (fstat(fd, &sb) < 0) { fprintf(stderr, "ERROR_FSTAT_FAILED\n"); close(fd); return 1; } ModelHeader header; if (read(fd, &header, sizeof(ModelHeader)) != sizeof(ModelHeader)) { fprintf(stderr, "ERROR_READING_HEADER\n"); close(fd); return 1; } if (memcmp(header.magic, "NANO", 4) != 0) { if (*(int*)header.magic == 8) { fprintf(stderr, "ERROR: Legacy model format detected (20-byte unaligned header). Expected magic 'NANO' (64-byte aligned header). Model rejected.\n"); } else { fprintf(stderr, "ERROR: Invalid model format. Expected magic 'NANO', got 0x%08X. Model rejected.\n", *(uint32_t*)header.magic); } close(fd); return 1; } if (header.version != 1 && header.version != 2) { fprintf(stderr, "ERROR: Unsupported model version %u. Expected version 1 or 2.\n", header.version); close(fd); return 1; } if (header.header_size != 64) { fprintf(stderr, "ERROR: Unsupported header size %u. Expected 64 bytes.\n", header.header_size); close(fd); return 1; } cfg.n_layer = header.n_layer; cfg.n_head = header.n_head; cfg.n_embd = header.n_embd; cfg.block_size = header.block_size; cfg.vocab_size = header.vocab_size; void* mapped_data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); if (mapped_data == MAP_FAILED) { fprintf(stderr, "ERROR_MMAP_FAILED\n"); close(fd); return 1; } model_data_buffer = (float*)((char*)mapped_data + 64); #endif print_mem_stage("after_map"); map_weights(model_data_buffer, header.version); // Touch all weights to measure working set when ALL mapped weight pages are in RAM volatile float sum_touch = 0.0f; long long total_floats = (header.version == 2) ? 51082752LL : 76814336LL; for (long long i = 0; i < total_floats; i += 1024) { sum_touch += model_data_buffer[i]; } print_mem_stage("after_touching_weights"); const int C = cfg.n_embd; const int L = cfg.n_layer; // Allocate all buffers ONCE KVCache kv; kv.k_cache = (float*)malloc((long long)L * cfg.block_size * C * sizeof(float)); kv.v_cache = (float*)malloc((long long)L * cfg.block_size * C * sizeof(float)); float* x = (float*)malloc(C * sizeof(float)); float* buf = (float*)malloc(C * sizeof(float)); float* qkv_buf = (float*)malloc(3 * C * sizeof(float)); float* attn_buf = (float*)malloc(cfg.n_head * cfg.block_size * sizeof(float)); float* ff_buf = (float*)malloc(4 * C * sizeof(float)); float* logits = (float*)malloc(cfg.vocab_size * sizeof(float)); print_mem_stage("after_kv_activation_alloc"); auto model_loaded_time = std::chrono::high_resolution_clock::now(); long long load_ms = std::chrono::duration_cast(model_loaded_time - start_time).count(); fprintf(stderr, "ENGINE_READY: load_ms=%lld\n", load_ms); fflush(stderr); char line[8192]; bool first_token_measured = false; while (fgets(line, sizeof(line), stdin)) { if (strncmp(line, "GEN ", 4) != 0) continue; char req_id[64]; int max_new_tokens, top_k; unsigned int seed; float temperature; char* token_str = line + 4; sscanf(token_str, "%s %d %f %d %u", req_id, &max_new_tokens, &temperature, &top_k, &seed); int spaces = 0; char* ids_str = token_str; while (*ids_str && spaces < 5) { if (*ids_str == ' ') spaces++; ids_str++; } std::vector input_ids; char* tok = strtok(ids_str, ", \n"); while (tok) { input_ids.push_back(atoi(tok)); tok = strtok(NULL, ", \n"); } if (input_ids.size() >= (size_t)cfg.block_size) input_ids.resize(cfg.block_size - 1); if (input_ids.size() + max_new_tokens > (size_t)cfg.block_size) { max_new_tokens = cfg.block_size - input_ids.size(); } if (temperature < 0.01f) temperature = 0.01f; if (top_k < 1) top_k = 1; if (top_k > cfg.vocab_size) top_k = cfg.vocab_size; srand(seed); // Reset per-op profiling timers prof_attn_us = 0; prof_mlp_us = 0; prof_lmhead_us = 0; prof_sample_us = 0; auto req_start = std::chrono::high_resolution_clock::now(); FILE* f_logits = NULL; if (dump_logits) f_logits = fopen("logits.bin", "wb"); for (int i = 0; i < (int)input_ids.size(); i++) { forward(input_ids[i], i, &kv, x, buf, qkv_buf, attn_buf, ff_buf, logits, false); if (f_logits) fwrite(logits, sizeof(float), cfg.vocab_size, f_logits); } if (f_logits) fclose(f_logits); auto prefill_done_time = std::chrono::high_resolution_clock::now(); long long prefill_ms = std::chrono::duration_cast(prefill_done_time - req_start).count(); int pos = input_ids.size(); int generated = 0; for (int i = 0; i < max_new_tokens; i++) { if (pos >= cfg.block_size) break; auto t_sample_start = std::chrono::high_resolution_clock::now(); for (int v = 0; v < cfg.vocab_size; v++) logits[v] /= temperature; std::vector> pairs(cfg.vocab_size); for (int v = 0; v < cfg.vocab_size; v++) pairs[v] = {logits[v], v}; std::partial_sort(pairs.begin(), pairs.begin() + top_k, pairs.end(), [](const std::pair& a, const std::pair& b) { return a.first > b.first; }); float sum = 0.0f; for (int j = 0; j < top_k; j++) { pairs[j].first = expf(pairs[j].first); sum += pairs[j].first; } for (int j = 0; j < top_k; j++) pairs[j].first /= sum; float r = (float)rand() / ((float)RAND_MAX + 1.0f); float cum = 0.0f; int next_id = pairs[0].second; for (int j = 0; j < top_k; j++) { cum += pairs[j].first; if (r <= cum) { next_id = pairs[j].second; break; } } auto t_sample_end = std::chrono::high_resolution_clock::now(); prof_sample_us += std::chrono::duration_cast(t_sample_end - t_sample_start).count(); printf("T %d\n", next_id); fflush(stdout); if (!first_token_measured) { print_mem_stage("after_first_token"); first_token_measured = true; } generated++; if (next_id == 50256) break; // Decode forward step with profiling forward(next_id, pos, &kv, x, buf, qkv_buf, attn_buf, ff_buf, logits, true); pos++; } auto decode_done_time = std::chrono::high_resolution_clock::now(); long long decode_ms = std::chrono::duration_cast(decode_done_time - prefill_done_time).count(); // Print per-op profiling summary to stderr long long prof_total = prof_attn_us + prof_mlp_us + prof_lmhead_us + prof_sample_us; if (prof_total > 0) { fprintf(stderr, "OP_PROFILE: attn=%lldus (%.1f%%) mlp=%lldus (%.1f%%) lm_head=%lldus (%.1f%%) sample=%lldus (%.1f%%) total=%lldus\n", prof_attn_us, (double)prof_attn_us * 100.0 / prof_total, prof_mlp_us, (double)prof_mlp_us * 100.0 / prof_total, prof_lmhead_us, (double)prof_lmhead_us * 100.0 / prof_total, prof_sample_us, (double)prof_sample_us * 100.0 / prof_total, prof_total); fflush(stderr); } printf("DONE %lld %lld %d\n", prefill_ms, decode_ms, generated); fflush(stdout); } return 0; }