| 369 | }; |
| 370 | |
| 371 | void run_perplexity( |
| 372 | Session& session, |
| 373 | const std::vector<int>& encoding |
| 374 | ) { |
| 375 | Model& model = session.model; |
| 376 | InferenceState& state = session.state; |
| 377 | Sampler& sampler = session.sampler; |
| 378 | |
| 379 | std::cout << "Model active bytes with full context window: " << model.active_bytes(model.config->max_seq_len) << std::endl; |
| 380 | |
| 381 | { |
| 382 | ProfileDisabledScope profile_disabled; |
| 383 | std::cout << "Running warmup..." << std::endl; |
| 384 | // Do one inference as warmup. |
| 385 | // On CPU, this ensures all tensors are loaded into memory via mmap. |
| 386 | model.forward(state, 0, 0); |
| 387 | std::cout << "Warmup complete" << std::endl; |
| 388 | } |
| 389 | |
| 390 | double sum_logprob = 0.0; |
| 391 | double ss_logprob = 0.0; |
| 392 | // Generates output logits for all tokens in the prompt and sum log probs to |
| 393 | // compute perplexity. |
| 394 | uint64_t start_ms = get_timestamp_ms(); |
| 395 | size_t read_bytes = 0; |
| 396 | size_t N = encoding.size() - 1; |
| 397 | for (size_t pos = 0; pos + 1 < encoding.size(); pos++) { |
| 398 | std::cout << "\r Computing perplexity..." << pos + 1 << "/" << N << std::flush; |
| 399 | |
| 400 | int token_id = encoding[pos]; |
| 401 | model.forward(state, token_id, pos); |
| 402 | read_bytes += model.active_bytes(pos); |
| 403 | |
| 404 | double logprob = std::log(sampler.sample_prob(encoding[pos + 1], state)); |
| 405 | sum_logprob += logprob; |
| 406 | ss_logprob += logprob * logprob; |
| 407 | } |
| 408 | std::cout << std::endl; |
| 409 | uint64_t end_ms = get_timestamp_ms(); |
| 410 | double elapsed_s = (end_ms - start_ms)/1000.0; |
| 411 | double perplexity = std::exp(-sum_logprob / N); |
| 412 | double perplexity_error = perplexity * std::sqrt( |
| 413 | (ss_logprob - sum_logprob * sum_logprob / N) / N / N |
| 414 | ); |
| 415 | std::cout << fmt::format( |
| 416 | "Stats:\n" |
| 417 | " {} tokens\n" |
| 418 | " perplexity: {:.5} ± {:.5}\n" |
| 419 | " throughput: {:.5}tok/s\n" |
| 420 | " latency: {:.5}s/tok\n" |
| 421 | " bandwidth: {:.5}GB/s\n" |
| 422 | " total: {:.5}s\n", |
| 423 | N, |
| 424 | perplexity, |
| 425 | perplexity_error, |
| 426 | N / elapsed_s, |
| 427 | elapsed_s / N, |
| 428 | ((double)read_bytes / 1e9) / elapsed_s, |
no test coverage detected