| 118 | } |
| 119 | |
| 120 | inline void write_bench_csv(const BenchmarkResults_t& results, const std::string& model_tag, const std::string& output_dir = ".") { |
| 121 | std::string safe_tag = sanitize_model_tag_for_filename(model_tag); |
| 122 | std::string date_stamp = get_date_yyyymmdd(); |
| 123 | std::string cpu_name = sanitize_model_tag_for_filename(get_cpu_name()); |
| 124 | std::string filename = output_dir; |
| 125 | if (!filename.empty() && filename.back() != '/' && filename.back() != '\\') { |
| 126 | filename += "/"; |
| 127 | } |
| 128 | filename += "bench_" + safe_tag + "_" + date_stamp; |
| 129 | if (!cpu_name.empty()) { |
| 130 | filename += "_" + cpu_name; |
| 131 | } |
| 132 | filename += ".csv"; |
| 133 | |
| 134 | std::ofstream out(filename, std::ios::out | std::ios::trunc); |
| 135 | if (!out.is_open()) { |
| 136 | header_print_r("ERROR", "Failed to open output file: " + filename); |
| 137 | return; |
| 138 | } |
| 139 | |
| 140 | out << "context_length_k,ttft_avg_s,ttft_std_s,ttft_min_s,ttft_max_s,prefill_avg_toks_per_s,prefill_std_toks_per_s,prefill_min_toks_per_s,prefill_max_toks_per_s,decoding_avg_toks_per_s,decoding_std_toks_per_s,decoding_min_toks_per_s,decoding_max_toks_per_s\n"; |
| 141 | |
| 142 | int stages = static_cast<int>(results.decoding_speed.size()); |
| 143 | for (int i = 0; i < stages; i++) { |
| 144 | int context_len_k = 1 << i; |
| 145 | std::vector<std::string> fields; |
| 146 | fields.reserve(13); |
| 147 | fields.push_back(std::to_string(context_len_k)); |
| 148 | |
| 149 | if (i < static_cast<int>(results.TTFT.size())) { |
| 150 | fields.push_back(format_float_csv(results.TTFT[i].average, 6)); |
| 151 | fields.push_back(format_float_csv(results.TTFT[i].std_variance, 6)); |
| 152 | fields.push_back(format_float_csv(results.TTFT[i].min, 6)); |
| 153 | fields.push_back(format_float_csv(results.TTFT[i].max, 6)); |
| 154 | } else { |
| 155 | fields.push_back(""); |
| 156 | fields.push_back(""); |
| 157 | fields.push_back(""); |
| 158 | fields.push_back(""); |
| 159 | } |
| 160 | |
| 161 | if (i < static_cast<int>(results.prefill_speed.size())) { |
| 162 | fields.push_back(format_float_csv(results.prefill_speed[i].average, 2)); |
| 163 | fields.push_back(format_float_csv(results.prefill_speed[i].std_variance, 2)); |
| 164 | fields.push_back(format_float_csv(results.prefill_speed[i].min, 2)); |
| 165 | fields.push_back(format_float_csv(results.prefill_speed[i].max, 2)); |
| 166 | } else { |
| 167 | fields.push_back(""); |
| 168 | fields.push_back(""); |
| 169 | fields.push_back(""); |
| 170 | fields.push_back(""); |
| 171 | } |
| 172 | |
| 173 | if (i < static_cast<int>(results.decoding_speed.size())) { |
| 174 | fields.push_back(format_float_csv(results.decoding_speed[i].average, 2)); |
| 175 | fields.push_back(format_float_csv(results.decoding_speed[i].std_variance, 2)); |
| 176 | fields.push_back(format_float_csv(results.decoding_speed[i].min, 2)); |
| 177 | fields.push_back(format_float_csv(results.decoding_speed[i].max, 2)); |
no test coverage detected