char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
14a9d09f7
char/aliceai-t5-moe
1#include <algorithm> 2#include <array> 3#include <cassert> 4#include <chrono> 5#include <cinttypes> 6#include <clocale> 7#include <cmath> 8#include <cstdio> 9#include <cstdlib> 10#include <cstring> 11#include <ctime> 12#include <iterator> 13#include <map> 14#include <numeric> 15#include <regex> 16#include <sstream> 17#include <string> 18#include <thread> 19#include <vector> 20#include <unordered_set> 21 22#include "arg.h" 23#include "build-info.h" 24#include "common.h" 25#include "download.h" 26#include "fit.h" 27#include "ggml.h" 28#include "llama.h" 29#include "log.h" 30 31#ifdef _WIN32 32# define WIN32_LEAN_AND_MEAN 33# ifndef NOMINMAX 34# define NOMINMAX 35# endif 36# include <windows.h> 37#endif 38 39// utils 40static uint64_t get_time_ns () { 41using clock = std::chrono::high_resolution_clock ; 42return std::chrono::nanoseconds (clock::now ().time_since_epoch ()).count (); 43} 44 45static bool tensor_buft_override_equal (const llama_model_tensor_buft_override & a ,const llama_model_tensor_buft_override & b ) { 46if (a .pattern != b .pattern ) { 47// cString comparison that may be null 48if (a .pattern == nullptr || b .pattern == nullptr ) { 49return false; 50 } 51if (strcmp (a .pattern ,b .pattern )!= 0 ) { 52return false; 53 } 54 } 55if (a .buft != b .buft ) { 56return false; 57 } 58return true; 59} 60 61static bool vec_tensor_buft_override_equal (const std::vector < llama_model_tensor_buft_override >& a ,const std::vector < llama_model_tensor_buft_override >& b ) { 62if (a .size ()!= b .size ()) { 63return false; 64 } 65for (size_t i = 0 ;i < a .size ();i ++ ) { 66if (!tensor_buft_override_equal (a [i ],b [i ])) { 67return false; 68 } 69 } 70return true; 71} 72 73static bool vec_vec_tensor_buft_override_equal (const std::vector < std::vector < llama_model_tensor_buft_override >>& a ,const std::vector < std::vector < llama_model_tensor_buft_override >>& b ) { 74if (a .size ()!= b .size ()) { 75return false; 76 } 77for (size_t i = 0 ;i < a .size ();i ++ ) { 78if (!vec_tensor_buft_override_equal (a [i ],b [i ])) { 79return false; 80 } 81 } 82return true; 83} 84 85template < class T > static std::string join (const std::vector < T > & values ,const std::string & delim ) { 86 std::ostringstream str ; 87for (size_t i = 0 ;i < values .size ();i ++ ) { 88str <<values [i ]; 89if (i < values .size ()- 1 ) { 90str <<delim ; 91 } 92 } 93return str .str (); 94} 95 96template < typename T ,typename F > static std::vector < std::string > transform_to_str (const std::vector < T > & values ,F f ) { 97 std::vector < std::string > str_values ; 98 std::transform (values .begin (),values .end (), std::back_inserter (str_values ),f ); 99return str_values ; 100} 101 102template < typename T > static T avg (const std::vector < T > & v ) { 103if (v .empty ()) { 104return 0 ; 105 } 106T sum = std::accumulate (v .begin (),v .end (),T (0 )); 107return sum / (T )v .size (); 108} 109 110template < typename T > static T stdev (const std::vector < T > & v ) { 111if (v .size () <=1 ) { 112return 0 ; 113 } 114T mean = avg (v ); 115T sq_sum = std::inner_product (v .begin (),v .end (),v .begin (),T (0 )); 116T stdev = std::sqrt (sq_sum / (T ) (v .size ()- 1 )- mean * mean * (T )v .size () / (T ) (v .size ()- 1 )); 117return stdev ; 118} 119 120static std::string get_cpu_info () { 121 std::vector < std::string > cpu_list ; 122for (size_t i = 0 ;i < ggml_backend_dev_count ();i ++ ) { 123auto * dev = ggml_backend_dev_get (i ); 124auto dev_type = ggml_backend_dev_type (dev ); 125if (dev_type == GGML_BACKEND_DEVICE_TYPE_CPU || dev_type == GGML_BACKEND_DEVICE_TYPE_ACCEL ) { 126cpu_list .push_back (ggml_backend_dev_description (dev )); 127 } 128 } 129return join (cpu_list ,", " ); 130} 131 132static std::string get_gpu_info () { 133 std::vector < std::string > gpu_list ; 134for (size_t i = 0 ;i < ggml_backend_dev_count ();i ++ ) { 135auto * dev = ggml_backend_dev_get (i ); 136auto dev_type = ggml_backend_dev_type (dev ); 137if (dev_type == GGML_BACKEND_DEVICE_TYPE_GPU || dev_type == GGML_BACKEND_DEVICE_TYPE_IGPU ) { 138gpu_list .push_back (ggml_backend_dev_description (dev )); 139 } 140 } 141return join (gpu_list ,", " ); 142} 143 144static std::vector < ggml_backend_dev_t > parse_devices_arg (const std::string & value ) { 145 std::vector < ggml_backend_dev_t > devices ; 146 std::string trimmed = string_strip (value ); 147if (trimmed .empty ()) { 148throw std::invalid_argument ("no devices specified" ); 149 } 150if (trimmed == "auto" ) { 151return devices ; 152 } 153 154auto dev_names = string_split < std::string > (trimmed ,'/' ); 155if (dev_names .size ()== 1 && string_strip (dev_names [0 ])== "none" ) { 156devices .push_back (nullptr ); 157return devices ; 158 } 159 160for (auto & name :dev_names ) { 161 std::string dev_name = string_strip (name ); 162if (dev_name .empty ()) { 163throw std::invalid_argument ("invalid device specification" ); 164 } 165auto * dev = ggml_backend_dev_by_name (dev_name .c_str ()); 166if (!dev || ggml_backend_dev_type (dev )== GGML_BACKEND_DEVICE_TYPE_CPU ) { 167throw std::invalid_argument (string_format ("invalid device: %s" ,dev_name .c_str ())); 168 } 169devices .push_back (dev ); 170 } 171 172devices .push_back (nullptr ); 173return devices ; 174} 175 176static void register_rpc_server_list (const std::string & servers ) { 177auto rpc_servers = string_split < std::string > (servers ,',' ); 178if (rpc_servers .empty ()) { 179throw std::invalid_argument ("no RPC servers specified" ); 180 } 181 182auto * rpc_reg = ggml_backend_reg_by_name ("RPC" ); 183if (!rpc_reg ) { 184throw std::invalid_argument ("failed to find RPC backend" ); 185 } 186 187using add_rpc_server_fn = ggml_backend_reg_t (* )(const char * endpoint ); 188auto * ggml_backend_rpc_add_server_fn = (add_rpc_server_fn )ggml_backend_reg_get_proc_address (rpc_reg ,"ggml_backend_rpc_add_server" ); 189if (!ggml_backend_rpc_add_server_fn ) { 190throw std::invalid_argument ("failed to find RPC add server function" ); 191 } 192for (const auto & server :rpc_servers ) { 193auto reg = ggml_backend_rpc_add_server_fn (server .c_str ()); 194ggml_backend_register (reg ); 195 } 196} 197 198static std::string devices_to_string (const std::vector < ggml_backend_dev_t > & devices ) { 199if (devices .empty ()) { 200return "auto" ; 201 } 202 203if (devices .size ()== 1 && devices [0 ]== nullptr ) { 204return "none" ; 205 } 206 207 std::vector < std::string > names ; 208for (auto * dev :devices ) { 209if (dev == nullptr ) { 210break ; 211 } 212names .push_back (ggml_backend_dev_name (dev )); 213 } 214 215return join (names ,"/" ); 216} 217 218// command line params 219enum output_formats {NONE ,CSV ,JSON ,JSONL ,MARKDOWN ,SQL }; 220 221static const char * output_format_str (output_formats format ) { 222switch (format ) { 223case NONE : 224return "none" ; 225case CSV : 226return "csv" ; 227case JSON : 228return "json" ; 229case JSONL : 230return "jsonl" ; 231case MARKDOWN : 232return "md" ; 233case SQL : 234return "sql" ; 235default : 236GGML_ABORT ("invalid output format" ); 237 } 238} 239 240static bool output_format_from_str (const std::string & s ,output_formats & format ) { 241if (s == "none" ) { 242format = NONE ; 243 }else if (s == "csv" ) { 244format = CSV ; 245 }else if (s == "json" ) { 246format = JSON ; 247 }else if (s == "jsonl" ) { 248format = JSONL ; 249 }else if (s == "md" ) { 250format = MARKDOWN ; 251 }else if (s == "sql" ) { 252format = SQL ; 253 }else { 254return false; 255 } 256return true; 257} 258 259static const char * split_mode_str (llama_split_mode mode ) { 260switch (mode ) { 261case LLAMA_SPLIT_MODE_NONE : 262return "none" ; 263case LLAMA_SPLIT_MODE_LAYER : 264return "layer" ; 265case LLAMA_SPLIT_MODE_ROW : 266return "row" ; 267case LLAMA_SPLIT_MODE_TENSOR : 268return "tensor" ; 269default : 270GGML_ABORT ("invalid split mode" ); 271 } 272} 273 274static const char * lazy_mode_str (llama_lazy_mode mode ) { 275switch (mode ) { 276case LLAMA_LAZY_MODE_OFF : 277return "off" ; 278case LLAMA_LAZY_MODE_AUTO : 279return "auto" ; 280case LLAMA_LAZY_MODE_ON : 281return "on" ; 282default : 283GGML_ABORT ("invalid lazy mode" ); 284 } 285} 286 287static std::string pair_str (const std::pair < int ,int > & p ) { 288static char buf [32 ]; 289snprintf (buf ,sizeof (buf ),"%d,%d" ,p .first ,p .second ); 290return buf ; 291} 292 293static std::vector < int > parse_int_range (const std::string & s ,bool allow_negative = false) { 294// first[-last[(+|*)step]] 295 std::regex range_regex (allow_negative 296 ?R"(^(-?\d+)(?:-(\d+)(?:([\+|\*])(\d+))?)?(?:,|$))" 297 :R"(^(\d+)(?:-(\d+)(?:([\+|\*])(\d+))?)?(?:,|$))" ); 298 299 std::smatch match ; 300 std::string::const_iterator search_start (s .cbegin ()); 301 std::vector < int > result ; 302while (std::regex_search (search_start ,s .cend (),match ,range_regex )) { 303int first = std::stoi (match [1 ]); 304int last = match [2 ].matched ? std::stoi (match [2 ]) :first ; 305char op = match [3 ].matched ?match [3 ].str ()[0 ] :'+' ; 306int step = match [4 ].matched ? std::stoi (match [4 ]) :1 ; 307 308for (int i = first ;i <=last ;) { 309result .push_back (i ); 310 311int prev_i = i ; 312 313if (op == '+' ) { 314i += step ; 315 }else if (op == '*' ) { 316i *=step ; 317 }else { 318throw std::invalid_argument ("invalid range format" ); 319 } 320 321if (i <=prev_i ) { 322throw std::invalid_argument ("invalid range" ); 323 } 324 } 325search_start = match .suffix ().first ; 326 } 327 328if (search_start != s .cend ()) { 329throw std::invalid_argument ("invalid range format" ); 330 } 331 332return result ; 333} 334 335struct cmd_params { 336 std::vector < std::string > model ; 337 std::vector < std::string > hf_repo ; 338 std::vector < std::string > hf_file ; 339 std::string hf_token ; 340bool offline ; 341 std::vector < int > n_prompt ; 342 std::vector < int > n_gen ; 343 std::vector < std::pair < int ,int >> n_pg ; 344 std::vector < int > n_depth ; 345 std::vector < int > n_batch ; 346 std::vector < int > n_ubatch ; 347 std::vector < ggml_type > type_k ; 348 std::vector < ggml_type > type_v ; 349 std::vector < int > n_threads ; 350 std::vector < std::string > cpu_mask ; 351 std::vector < bool > cpu_strict ; 352 std::vector < int > poll ; 353 std::vector < int > n_gpu_layers ; 354 std::vector < int > n_cpu_moe ; 355 std::vector < llama_split_mode > split_mode ; 356 std::vector < llama_load_mode > load_mode ; 357 std::vector < llama_lazy_mode > lazy_mode ; 358 std::vector < int > main_gpu ; 359 std::vector < bool > no_kv_offload ; 360 std::vector < llama_flash_attn_type > flash_attn ; 361 std::vector < std::vector < ggml_backend_dev_t >> devices ; 362 std::vector < std::vector < float >> tensor_split ; 363 std::vector < std::vector < llama_model_tensor_buft_override >> tensor_buft_overrides ; 364 std::vector < bool > embeddings ; 365 std::vector < bool > no_op_offload ; 366 std::vector < bool > no_host ; 367 std::vector < size_t > fit_params_target ; 368 std::vector < uint32_t > fit_params_min_ctx ; 369ggml_numa_strategy numa ; 370int reps ; 371ggml_sched_priority prio ; 372int delay ; 373bool verbose ; 374bool progress ; 375bool no_warmup ; 376output_formats output_format ; 377output_formats output_format_stderr ; 378}; 379 380static const cmd_params cmd_params_defaults = { 381/* model */ {"models/7B/ggml-model-q4_0.gguf" }, 382/* hf_repo */ {}, 383/* hf_file */ {}, 384/* hf_token */ "" , 385/* offline */ false, 386/* n_prompt */ {512 }, 387/* n_gen */ {128 }, 388/* n_pg */ {}, 389/* n_depth */ {0 }, 390/* n_batch */ {2048 }, 391/* n_ubatch */ {512 }, 392/* type_k */ {GGML_TYPE_F16 }, 393/* type_v */ {GGML_TYPE_F16 }, 394/* n_threads */ {common_cpu_get_num_math () }, 395/* cpu_mask */ {"0x0" }, 396/* cpu_strict */ { false }, 397/* poll */ {50 }, 398/* n_gpu_layers */ {-1 }, 399/* n_cpu_moe */ {0 }, 400/* split_mode */ {LLAMA_SPLIT_MODE_LAYER }, 401/* load_mode */ {LLAMA_LOAD_MODE_AUTO }, 402/* lazy_mode */ {LLAMA_LAZY_MODE_AUTO }, 403/* main_gpu */ {0 }, 404/* no_kv_offload */ { false }, 405/* flash_attn */ {LLAMA_FLASH_ATTN_TYPE_AUTO }, 406/* devices */ { {} }, 407/* tensor_split */ { std::vector < float > (llama_max_devices (),0.0f ) }, 408/* tensor_buft_overrides*/ { std::vector < llama_model_tensor_buft_override > { {nullptr ,nullptr } } }, 409/* embeddings */ { false }, 410/* no_op_offload */ { false }, 411/* no_host */ { false }, 412/* fit_params_target */ {0 }, 413/* fit_params_min_ctx */ {0 }, 414/* numa */ GGML_NUMA_STRATEGY_DISABLED , 415/* reps */ 5 , 416/* prio */ GGML_SCHED_PRIO_NORMAL , 417/* delay */ 0 , 418/* verbose */ false, 419/* progress */ false, 420/* no_warmup */ false, 421/* output_format */ MARKDOWN , 422/* output_format_stderr */ NONE , 423}; 424 425static void print_usage (int /* argc */ ,char ** argv ) { 426printf ("usage: %s [options]\n" ,argv [0 ]); 427printf ("\n" ); 428printf ("options:\n" ); 429printf (" -h, --help\n" ); 430printf (" --numa <distribute|isolate|numactl> numa mode (default: disabled)\n" ); 431printf (" -r, --repetitions <n> number of times to repeat each test (default: %d)\n" ,cmd_params_defaults .reps ); 432printf (" --prio <-1|0|1|2|3> process/thread priority (default: %d)\n" ,cmd_params_defaults .prio ); 433printf (" --delay <0...N> (seconds) delay between each test (default: %d)\n" ,cmd_params_defaults .delay ); 434printf (" -o, --output <csv|json|jsonl|md|sql> output format printed to stdout (default: %s)\n" ,output_format_str (cmd_params_defaults .output_format )); 435printf (" -oe, --output-err <csv|json|jsonl|md|sql> output format printed to stderr (default: %s)\n" ,output_format_str (cmd_params_defaults .output_format_stderr )); 436printf (" --list-devices list available devices and exit\n" ); 437printf (" -v, --verbose verbose output\n" ); 438printf (" --progress print test progress indicators\n" ); 439printf (" --no-warmup skip warmup runs before benchmarking\n" ); 440printf (" -fitt, --fit-target <MiB> fit model to device memory with this margin per device in MiB (default: off)\n" ); 441printf (" -fitc, --fit-ctx <n> minimum ctx size for --fit-target (default: 4096)\n" ); 442if (llama_supports_rpc ()) { 443printf (" -rpc, --rpc <rpc_servers> register RPC devices (comma separated)\n" ); 444 } 445printf ("\n" ); 446printf ("test parameters:\n" ); 447printf (" -m, --model <filename> (default: %s)\n" ,join (cmd_params_defaults .model ,"," ).c_str ()); 448printf (" -hf, -hfr, --hf-repo <user>/<model>[:quant] Hugging Face model repository; quant is optional, case-insensitive\n" ); 449printf (" default to Q4_K_M, or falls back to the first file in the repo if Q4_K_M doesn't exist.\n" ); 450printf (" example: ggml-org/GLM-4.7-Flash-GGUF:Q4_K_M\n" ); 451printf (" (default: unused)\n" ); 452printf (" -hff, --hf-file <file> Hugging Face model file. If specified, it will override the quant in --hf-repo\n" ); 453printf (" (default: unused)\n" ); 454printf (" -hft, --hf-token <token> Hugging Face access token\n" ); 455printf (" (default: value from HF_TOKEN environment variable)\n" ); 456printf (" --offline Offline mode: forces use of cache, prevents network access\n" ); 457printf (" (default: disabled)\n" ); 458printf (" -p, --n-prompt <n> (default: %s)\n" ,join (cmd_params_defaults .n_prompt ,"," ).c_str ()); 459printf (" -n, --n-gen <n> (default: %s)\n" ,join (cmd_params_defaults .n_gen ,"," ).c_str ()); 460printf (" -pg <pp,tg> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .n_pg ,pair_str ),"," ).c_str ()); 461printf (" -d, --n-depth <n> (default: %s)\n" ,join (cmd_params_defaults .n_depth ,"," ).c_str ()); 462printf (" -b, --batch-size <n> (default: %s)\n" ,join (cmd_params_defaults .n_batch ,"," ).c_str ()); 463printf (" -ub, --ubatch-size <n> (default: %s)\n" ,join (cmd_params_defaults .n_ubatch ,"," ).c_str ()); 464printf (" -ctk, --cache-type-k <t> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .type_k ,ggml_type_name ),"," ).c_str ()); 465printf (" -ctv, --cache-type-v <t> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .type_v ,ggml_type_name ),"," ).c_str ()); 466printf (" -t, --threads <n> (default: %s)\n" ,join (cmd_params_defaults .n_threads ,"," ).c_str ()); 467printf (" -C, --cpu-mask <hex,hex> (default: %s)\n" ,join (cmd_params_defaults .cpu_mask ,"," ).c_str ()); 468printf (" --cpu-strict <0|1> (default: %s)\n" ,join (cmd_params_defaults .cpu_strict ,"," ).c_str ()); 469printf (" --poll <0...100> (default: %s)\n" ,join (cmd_params_defaults .poll ,"," ).c_str ()); 470printf (" -ngl, --n-gpu-layers <n> (default: %s)\n" ,join (cmd_params_defaults .n_gpu_layers ,"," ).c_str ()); 471printf (" -ncmoe, --n-cpu-moe <n> (default: %s)\n" ,join (cmd_params_defaults .n_cpu_moe ,"," ).c_str ()); 472printf (" -sm, --split-mode <none|layer|row|tensor> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .split_mode ,split_mode_str ),"," ).c_str ()); 473printf (" -mg, --main-gpu <i> (default: %s)\n" ,join (cmd_params_defaults .main_gpu ,"," ).c_str ()); 474printf (" -nkvo, --no-kv-offload <0|1> (default: %s)\n" ,join (cmd_params_defaults .no_kv_offload ,"," ).c_str ()); 475printf (" -fa, --flash-attn <on|off|auto> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .flash_attn ,llama_flash_attn_type_name ),"," ).c_str ()); 476printf (" -dev, --device <dev0/dev1/...> (default: auto)\n" ); 477printf (" -lm, --load-mode <auto|none|mmap|mlock|mmap+mlock|dio> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .load_mode ,llama_load_mode_name ),"," ).c_str ()); 478printf (" -lzm, --lazy-mode <on|auto|off> (default: %s)\n" ,join (transform_to_str (cmd_params_defaults .lazy_mode ,lazy_mode_str ),"," ).c_str ()); 479printf (" -embd, --embeddings <0|1> (default: %s)\n" ,join (cmd_params_defaults .embeddings ,"," ).c_str ()); 480printf (" -ts, --tensor-split <ts0/ts1/..> (default: 0)\n" ); 481printf (" -ot --override-tensor <tensor name pattern>=<buffer type>;...\n" ); 482printf (" (default: disabled)\n" ); 483printf (" -nopo, --no-op-offload <0|1> (default: 0)\n" ); 484printf (" --no-host <0|1> (default: %s)\n" ,join (cmd_params_defaults .no_host ,"," ).c_str ()); 485printf ("\n" ); 486printf ( 487"Multiple values can be given for each parameter by separating them with ','\n" 488"or by specifying the parameter multiple times. Ranges can be given as\n" 489"'first-last' or 'first-last+step' or 'first-last*mult'.\n" ); 490} 491 492static ggml_type ggml_type_from_name (const std::string & s ) { 493if (s == "f16" ) { 494return GGML_TYPE_F16 ; 495 } 496if (s == "bf16" ) { 497return GGML_TYPE_BF16 ; 498 } 499if (s == "q8_0" ) { 500return GGML_TYPE_Q8_0 ; 501 } 502if (s == "q4_0" ) { 503return GGML_TYPE_Q4_0 ; 504 } 505if (s == "q4_1" ) { 506return GGML_TYPE_Q4_1 ; 507 } 508if (s == "q5_0" ) { 509return GGML_TYPE_Q5_0 ; 510 } 511if (s == "q5_1" ) { 512return GGML_TYPE_Q5_1 ; 513 } 514if (s == "iq4_nl" ) { 515return GGML_TYPE_IQ4_NL ; 516 } 517 518return GGML_TYPE_COUNT ; 519} 520 521static cmd_params parse_cmd_params (int argc ,char ** argv ) { 522cmd_params params ; 523 std::string arg ; 524bool invalid_param = false; 525const std::string arg_prefix = "--" ; 526const char split_delim = ',' ; 527 528params .verbose = cmd_params_defaults .verbose ; 529params .output_format = cmd_params_defaults .output_format ; 530params .output_format_stderr = cmd_params_defaults .output_format_stderr ; 531params .reps = cmd_params_defaults .reps ; 532params .numa = cmd_params_defaults .numa ; 533params .prio = cmd_params_defaults .prio ; 534params .delay = cmd_params_defaults .delay ; 535params .progress = cmd_params_defaults .progress ; 536params .no_warmup = cmd_params_defaults .no_warmup ; 537params .offline = cmd_params_defaults .offline ; 538 539if (const char * env = getenv ("HF_TOKEN" )) { 540params .hf_token = env ; 541 } 542 543for (int i = 1 ;i < argc ;i ++ ) { 544arg = argv [i ]; 545if (arg .compare (0 ,arg_prefix .size (),arg_prefix )== 0 ) { 546 std::replace (arg .begin (),arg .end (),'_' ,'-' ); 547 } 548 549try { 550if (arg == "-h" || arg == "--help" ) { 551print_usage (argc ,argv ); 552exit (0 ); 553 }else if (arg == "-m" || arg == "--model" ) { 554if (++ i >=argc ) { 555invalid_param = true; 556break ; 557 } 558auto p = string_split < std::string > (argv [i ],split_delim ); 559params .model .insert (params .model .end (),p .begin (),p .end ()); 560 }else if (arg == "-hf" || arg == "-hfr" || arg == "--hf-repo" ) { 561if (++ i >=argc ) { 562invalid_param = true; 563break ; 564 } 565auto p = string_split < std::string > (argv [i ],split_delim ); 566params .hf_repo .insert (params .hf_repo .end (),p .begin (),p .end ()); 567 }else if (arg == "-hff" || arg == "--hf-file" ) { 568if (++ i >=argc ) { 569invalid_param = true; 570break ; 571 } 572auto p = string_split < std::string > (argv [i ],split_delim ); 573params .hf_file .insert (params .hf_file .end (),p .begin (),p .end ()); 574 }else if (arg == "-hft" || arg == "--hf-token" ) { 575if (++ i >=argc ) { 576invalid_param = true; 577break ; 578 } 579params .hf_token = argv [i ]; 580 }else if (arg == "--offline" ) { 581params .offline = true; 582 }else if (arg == "-p" || arg == "--n-prompt" ) { 583if (++ i >=argc ) { 584invalid_param = true; 585break ; 586 } 587auto p = parse_int_range (argv [i ]); 588params .n_prompt .insert (params .n_prompt .end (),p .begin (),p .end ()); 589 }else if (arg == "-n" || arg == "--n-gen" ) { 590if (++ i >=argc ) { 591invalid_param = true; 592break ; 593 } 594auto p = parse_int_range (argv [i ]); 595params .n_gen .insert (params .n_gen .end (),p .begin (),p .end ()); 596 }else if (arg == "-pg" ) { 597if (++ i >=argc ) { 598invalid_param = true; 599break ; 600 } 601auto p = string_split < std::string > (argv [i ],',' ); 602if (p .size ()!= 2 ) { 603invalid_param = true; 604break ; 605 } 606params .n_pg .push_back ({ std::stoi (p [0 ]), std::stoi (p [1 ]) }); 607 }else if (arg == "-d" || arg == "--n-depth" ) { 608if (++ i >=argc ) { 609invalid_param = true; 610break ; 611 } 612auto p = parse_int_range (argv [i ]); 613params .n_depth .insert (params .n_depth .end (),p .begin (),p .end ()); 614 }else if (arg == "-b" || arg == "--batch-size" ) { 615if (++ i >=argc ) { 616invalid_param = true; 617break ; 618 } 619auto p = parse_int_range (argv [i ]); 620params .n_batch .insert (params .n_batch .end (),p .begin (),p .end ()); 621 }else if (arg == "-ub" || arg == "--ubatch-size" ) { 622if (++ i >=argc ) { 623invalid_param = true; 624break ; 625 } 626auto p = parse_int_range (argv [i ]); 627params .n_ubatch .insert (params .n_ubatch .end (),p .begin (),p .end ()); 628 }else if (arg == "-ctk" || arg == "--cache-type-k" ) { 629if (++ i >=argc ) { 630invalid_param = true; 631break ; 632 } 633auto p = string_split < std::string > (argv [i ],split_delim ); 634 635 std::vector < ggml_type > types ; 636for (const auto & t :p ) { 637ggml_type gt = ggml_type_from_name (t ); 638if (gt == GGML_TYPE_COUNT ) { 639invalid_param = true; 640break ; 641 } 642types .push_back (gt ); 643 } 644if (invalid_param ) { 645break ; 646 } 647params .type_k .insert (params .type_k .end (),types .begin (),types .end ()); 648 }else if (arg == "-ctv" || arg == "--cache-type-v" ) { 649if (++ i >=argc ) { 650invalid_param = true; 651break ; 652 } 653auto p = string_split < std::string > (argv [i ],split_delim ); 654 655 std::vector < ggml_type > types ; 656for (const auto & t :p ) { 657ggml_type gt = ggml_type_from_name (t ); 658if (gt == GGML_TYPE_COUNT ) { 659invalid_param = true; 660break ; 661 } 662types .push_back (gt ); 663 } 664if (invalid_param ) { 665break ; 666 } 667params .type_v .insert (params .type_v .end (),types .begin (),types .end ()); 668 }else if (arg == "-dev" || arg == "--device" ) { 669if (++ i >=argc ) { 670invalid_param = true; 671break ; 672 } 673auto combos = string_split < std::string > (argv [i ],split_delim ); 674for (const auto & combo :combos ) { 675try { 676params .devices .push_back (parse_devices_arg (combo )); 677 }catch (const std::exception & e ) { 678fprintf (stderr ,"error: %s\n" ,e .what ()); 679invalid_param = true; 680break ; 681 } 682 } 683if (invalid_param ) { 684break ; 685 } 686 }else if (arg == "--list-devices" ) { 687common_print_available_devices (); 688exit (0 ); 689 }else if (arg == "-t" || arg == "--threads" ) { 690if (++ i >=argc ) { 691invalid_param = true; 692break ; 693 } 694auto p = parse_int_range (argv [i ]); 695params .n_threads .insert (params .n_threads .end (),p .begin (),p .end ()); 696 }else if (arg == "-C" || arg == "--cpu-mask" ) { 697if (++ i >=argc ) { 698invalid_param = true; 699break ; 700 } 701auto p = string_split < std::string > (argv [i ],split_delim ); 702params .cpu_mask .insert (params .cpu_mask .end (),p .begin (),p .end ()); 703 }else if (arg == "--cpu-strict" ) { 704if (++ i >=argc ) { 705invalid_param = true; 706break ; 707 } 708auto p = string_split < bool > (argv [i ],split_delim ); 709params .cpu_strict .insert (params .cpu_strict .end (),p .begin (),p .end ()); 710 }else if (arg == "--poll" ) { 711if (++ i >=argc ) { 712invalid_param = true; 713break ; 714 } 715auto p = parse_int_range (argv [i ]); 716params .poll .insert (params .poll .end (),p .begin (),p .end ()); 717 }else if (arg == "-ngl" || arg == "--n-gpu-layers" ) { 718if (++ i >=argc ) { 719invalid_param = true; 720break ; 721 } 722auto p = parse_int_range (argv [i ],/*allow_negative=*/ true); 723params .n_gpu_layers .insert (params .n_gpu_layers .end (),p .begin (),p .end ()); 724 }else if (arg == "-ncmoe" || arg == "--n-cpu-moe" ) { 725if (++ i >=argc ) { 726invalid_param = true; 727break ; 728 } 729auto p = parse_int_range (argv [i ]); 730params .n_cpu_moe .insert (params .n_cpu_moe .end (),p .begin (),p .end ()); 731 }else if (llama_supports_rpc ()&& (arg == "-rpc" || arg == "--rpc" )) { 732if (++ i >=argc ) { 733invalid_param = true; 734break ; 735 } 736try { 737register_rpc_server_list (argv [i ]); 738 }catch (const std::exception & e ) { 739fprintf (stderr ,"error: %s\n" ,e .what ()); 740invalid_param = true; 741break ; 742 } 743 }else if (arg == "-sm" || arg == "--split-mode" ) { 744if (++ i >=argc ) { 745invalid_param = true; 746break ; 747 } 748auto p = string_split < std::string > (argv [i ],split_delim ); 749 750 std::vector < llama_split_mode > modes ; 751for (const auto & m :p ) { 752llama_split_mode mode ; 753if (m == "none" ) { 754mode = LLAMA_SPLIT_MODE_NONE ; 755 }else if (m == "layer" ) { 756mode = LLAMA_SPLIT_MODE_LAYER ; 757 }else if (m == "row" ) { 758mode = LLAMA_SPLIT_MODE_ROW ; 759 }else if (m == "tensor" ) { 760mode = LLAMA_SPLIT_MODE_TENSOR ; 761 }else { 762invalid_param = true; 763break ; 764 } 765modes .push_back (mode ); 766 } 767if (invalid_param ) { 768break ; 769 } 770params .split_mode .insert (params .split_mode .end (),modes .begin (),modes .end ()); 771 }else if (arg == "-lm" || arg == "--load-mode" ) { 772if (++ i >=argc ) { 773invalid_param = true; 774break ; 775 } 776auto p = string_split < std::string > (argv [i ],split_delim ); 777 778 std::vector < llama_load_mode > modes ; 779for (const auto & m :p ) { 780llama_load_mode mode ; 781if (m == "auto" ) { 782mode = LLAMA_LOAD_MODE_AUTO ; 783 }else if (m == "none" ) { 784mode = LLAMA_LOAD_MODE_NONE ; 785 }else if (m == "mmap" ) { 786mode = LLAMA_LOAD_MODE_MMAP ; 787 }else if (m == "mlock" ) { 788mode = LLAMA_LOAD_MODE_MLOCK ; 789 }else if (m == "mmap+mlock" ) { 790mode = LLAMA_LOAD_MODE_MMAP_MLOCK ; 791 }else if (m == "dio" ) { 792mode = LLAMA_LOAD_MODE_DIRECT_IO ; 793 }else { 794invalid_param = true; 795break ; 796 } 797modes .push_back (mode ); 798 } 799if (invalid_param ) { 800break ; 801 } 802params .load_mode .insert (params .load_mode .end (),modes .begin (),modes .end ()); 803 }else if (arg == "-lzm" || arg == "--lazy-mode" ) { 804if (++ i >=argc ) { 805invalid_param = true; 806break ; 807 } 808auto p = string_split < std::string > (argv [i ],split_delim ); 809 810 std::vector < llama_lazy_mode > modes ; 811for (const auto & m :p ) { 812llama_lazy_mode mode ; 813if (m == "on" ) { 814mode = LLAMA_LAZY_MODE_ON ; 815 }else if (m == "auto" ) { 816mode = LLAMA_LAZY_MODE_AUTO ; 817 }else if (m == "off" ) { 818mode = LLAMA_LAZY_MODE_OFF ; 819 }else { 820invalid_param = true; 821break ; 822 } 823modes .push_back (mode ); 824 } 825if (invalid_param ) { 826break ; 827 } 828params .lazy_mode .insert (params .lazy_mode .end (),modes .begin (),modes .end ()); 829 }else if (arg == "-mg" || arg == "--main-gpu" ) { 830if (++ i >=argc ) { 831invalid_param = true; 832break ; 833 } 834params .main_gpu = parse_int_range (argv [i ]); 835 }else if (arg == "-nkvo" || arg == "--no-kv-offload" ) { 836if (++ i >=argc ) { 837invalid_param = true; 838break ; 839 } 840auto p = string_split < bool > (argv [i ],split_delim ); 841params .no_kv_offload .insert (params .no_kv_offload .end (),p .begin (),p .end ()); 842 }else if (arg == "--numa" ) { 843if (++ i >=argc ) { 844invalid_param = true; 845break ; 846 } 847 std::string value (argv [i ]); 848if (value == "distribute" || value == "" ) { 849params .numa = GGML_NUMA_STRATEGY_DISTRIBUTE ; 850 }else if (value == "isolate" ) { 851params .numa = GGML_NUMA_STRATEGY_ISOLATE ; 852 }else if (value == "numactl" ) { 853params .numa = GGML_NUMA_STRATEGY_NUMACTL ; 854 }else { 855invalid_param = true; 856break ; 857 } 858 }else if (arg == "-fa" || arg == "--flash-attn" ) { 859if (++ i >=argc ) { 860invalid_param = true; 861break ; 862 } 863auto p = string_split < std::string > (argv [i ],split_delim ); 864 865 std::vector < llama_flash_attn_type > types ; 866for (const auto & v :p ) { 867llama_flash_attn_type type ; 868if (common_arg_utils::is_truthy (v )) { 869type = LLAMA_FLASH_ATTN_TYPE_ENABLED ; 870 }else if (common_arg_utils::is_falsey (v )) { 871type = LLAMA_FLASH_ATTN_TYPE_DISABLED ; 872 }else if (common_arg_utils::is_autoy (v )) { 873type = LLAMA_FLASH_ATTN_TYPE_AUTO ; 874 }else { 875invalid_param = true; 876break ; 877 } 878types .push_back (type ); 879 } 880if (invalid_param ) { 881break ; 882 } 883params .flash_attn .insert (params .flash_attn .end (),types .begin (),types .end ()); 884 }else if (arg == "-embd" || arg == "--embeddings" ) { 885if (++ i >=argc ) { 886invalid_param = true; 887break ; 888 } 889auto p = string_split < bool > (argv [i ],split_delim ); 890params .embeddings .insert (params .embeddings .end (),p .begin (),p .end ()); 891 }else if (arg == "-nopo" || arg == "--no-op-offload" ) { 892if (++ i >=argc ) { 893invalid_param = true; 894break ; 895 } 896auto p = string_split < bool > (argv [i ],split_delim ); 897params .no_op_offload .insert (params .no_op_offload .end (),p .begin (),p .end ()); 898 }else if (arg == "--no-host" ) { 899if (++ i >=argc ) { 900invalid_param = true; 901break ; 902 } 903auto p = string_split < bool > (argv [i ],split_delim ); 904params .no_host .insert (params .no_host .end (),p .begin (),p .end ()); 905 }else if (arg == "-ts" || arg == "--tensor-split" ) { 906if (++ i >=argc ) { 907invalid_param = true; 908break ; 909 } 910for (auto ts :string_split < std::string > (argv [i ],split_delim )) { 911// split string by ; and / 912const std::regex regex {R"([;/]+)" }; 913 std::sregex_token_iterator it {ts .begin (),ts .end (),regex ,-1 }; 914 std::vector < std::string > split_arg {it , {} }; 915GGML_ASSERT (split_arg .size () <=llama_max_devices ()); 916 917 std::vector < float > tensor_split (llama_max_devices ()); 918for (size_t i = 0 ;i < llama_max_devices ();++ i ) { 919if (i < split_arg .size ()) { 920tensor_split [i ]= std::stof (split_arg [i ]); 921 }else { 922tensor_split [i ]= 0.0f ; 923 } 924 } 925params .tensor_split .push_back (tensor_split ); 926 } 927 }else if (arg == "-ot" || arg == "--override-tensor" ) { 928if (++ i >=argc ) { 929invalid_param = true; 930break ; 931 } 932auto * value = argv [i ]; 933/* static */ std::map < std::string ,ggml_backend_buffer_type_t > buft_list ; 934if (buft_list .empty ()) { 935// enumerate all the devices and add their buffer types to the list 936for (size_t i = 0 ;i < ggml_backend_dev_count ();++ i ) { 937auto * dev = ggml_backend_dev_get (i ); 938auto * buft = ggml_backend_dev_buffer_type (dev ); 939if (buft ) { 940buft_list [ggml_backend_buft_name (buft )]= buft ; 941 } 942 } 943 } 944auto override_group_span_len = std::strcspn (value ,"," ); 945bool last_group = false; 946do { 947if (override_group_span_len == 0 ) { 948// Adds an empty override-tensors for an empty span 949params .tensor_buft_overrides .push_back ({{}}); 950if (value [override_group_span_len ]== '\0' ) { 951value = & value [override_group_span_len ]; 952last_group = true; 953 }else { 954value = & value [override_group_span_len + 1 ]; 955override_group_span_len = std::strcspn (value ,"," ); 956 } 957continue ; 958 } 959// Stamps null terminators into the argv 960// value for this option to avoid the 961// memory leak present in the implementation 962// over in arg.cpp. Acceptable because we 963// only parse these args once in this program. 964auto * override_group = value ; 965if (value [override_group_span_len ]== '\0' ) { 966value = & value [override_group_span_len ]; 967last_group = true; 968 }else { 969value [override_group_span_len ]= '\0' ; 970value = & value [override_group_span_len + 1 ]; 971 } 972 std::vector < llama_model_tensor_buft_override > group_tensor_buft_overrides {}; 973auto override_span_len = std::strcspn (override_group ,";" ); 974while (override_span_len > 0 ) { 975auto * override = override_group ; 976if (override_group [override_span_len ]!= '\0' ) { 977override_group [override_span_len ]= '\0' ; 978override_group = & override_group [override_span_len + 1 ]; 979 }else { 980override_group = & override_group [override_span_len ]; 981 } 982auto tensor_name_span_len = std::strcspn (override ,"=" ); 983if (tensor_name_span_len >=override_span_len ) { 984invalid_param = true; 985break ; 986 } 987override [tensor_name_span_len ]= '\0' ; 988auto * tensor_name = override ; 989auto * buffer_type = & override [tensor_name_span_len + 1 ]; 990if (buft_list .find (buffer_type )== buft_list .end ()) { 991printf ("error: unrecognized buffer type '%s'\n" ,buffer_type ); 992printf ("Available buffer types:\n" ); 993for (const auto & it :buft_list ) { 994printf (" %s\n" ,ggml_backend_buft_name (it .second )); 995 } 996invalid_param = true; 997break ; 998 } 999group_tensor_buft_overrides .push_back ({tensor_name ,buft_list .at (buffer_type )}); 1000override_span_len = std::strcspn (override_group ,";" ); 1001 } 1002if (invalid_param ) { 1003break ; 1004 } 1005group_tensor_buft_overrides .push_back ({nullptr ,nullptr }); 1006params .tensor_buft_overrides .push_back (group_tensor_buft_overrides ); 1007override_group_span_len = std::strcspn (value ,"," ); 1008 }while (!last_group ); 1009 }else if (arg == "-r" || arg == "--repetitions" ) { 1010if (++ i >=argc ) { 1011invalid_param = true; 1012break ; 1013 } 1014params .reps = std::stoi (argv [i ]); 1015 }else if (arg == "--prio" ) { 1016if (++ i >=argc ) { 1017invalid_param = true; 1018break ; 1019 } 1020params .prio = (enum ggml_sched_priority ) std::stoi (argv [i ]); 1021 }else if (arg == "--delay" ) { 1022if (++ i >=argc ) { 1023invalid_param = true; 1024break ; 1025 } 1026params .delay = std::stoi (argv [i ]); 1027 }else if (arg == "-o" || arg == "--output" ) { 1028if (++ i >=argc ) { 1029invalid_param = true; 1030break ; 1031 } 1032invalid_param = !output_format_from_str (argv [i ],params .output_format ); 1033 }else if (arg == "-oe" || arg == "--output-err" ) { 1034if (++ i >=argc ) { 1035invalid_param = true; 1036break ; 1037 } 1038invalid_param = !output_format_from_str (argv [i ],params .output_format_stderr ); 1039 }else if (arg == "-v" || arg == "--verbose" ) { 1040params .verbose = true; 1041 }else if (arg == "--progress" ) { 1042params .progress = true; 1043 }else if (arg == "--no-warmup" ) { 1044params .no_warmup = true; 1045 }else if (arg == "-fitt" || arg == "--fit-target" ) { 1046if (++ i >=argc ) { 1047invalid_param = true; 1048break ; 1049 } 1050auto p = string_split < std::string > (argv [i ],split_delim ); 1051for (const auto & v :p ) { 1052params .fit_params_target .push_back (std::stoull (v )); 1053 } 1054 }else if (arg == "-fitc" || arg == "--fit-ctx" ) { 1055if (++ i >=argc ) { 1056invalid_param = true; 1057break ; 1058 } 1059auto p = string_split < std::string > (argv [i ],split_delim ); 1060for (const auto & v :p ) { 1061params .fit_params_min_ctx .push_back (std::stoul (v )); 1062 } 1063 }else { 1064invalid_param = true; 1065break ; 1066 } 1067 }catch (const std::exception & e ) { 1068fprintf (stderr ,"error: %s\n" ,e .what ()); 1069invalid_param = true; 1070break ; 1071 } 1072 } 1073 1074if (invalid_param ) { 1075fprintf (stderr ,"error: invalid parameter for argument: %s\n" ,arg .c_str ()); 1076print_usage (argc ,argv ); 1077exit (1 ); 1078 } 1079 1080if (!params .hf_repo .empty ()) { 1081for (size_t i = 0 ;i < params .hf_repo .size ();i ++ ) { 1082common_params p ; 1083p .hf_token = params .hf_token ; 1084p .offline = params .offline ; 1085p .model .hf_repo = params .hf_repo [i ]; 1086if (!params .hf_file .empty ()&& !params .hf_file [i ].empty ()) { 1087p .model .hf_file = params .hf_file [i ]; 1088 } 1089 1090// only the text model file is needed 1091common_models_handler models_handler = common_models_handler_init (p ,LLAMA_EXAMPLE_BENCH ); 1092common_models_handler_apply (models_handler ,p ); 1093if (p .model .path .empty ()) { 1094fprintf (stderr ,"error: failed to download model from HuggingFace\n" ); 1095exit (1 ); 1096 } 1097 1098params .model .push_back (p .model .path ); 1099 } 1100 } 1101 1102// set defaults 1103if (params .model .empty ()) { 1104params .model = cmd_params_defaults .model ; 1105 } 1106if (params .n_prompt .empty ()) { 1107params .n_prompt = cmd_params_defaults .n_prompt ; 1108 } 1109if (params .n_gen .empty ()) { 1110params .n_gen = cmd_params_defaults .n_gen ; 1111 } 1112if (params .n_pg .empty ()) { 1113params .n_pg = cmd_params_defaults .n_pg ; 1114 } 1115if (params .n_depth .empty ()) { 1116params .n_depth = cmd_params_defaults .n_depth ; 1117 } 1118if (params .n_batch .empty ()) { 1119params .n_batch = cmd_params_defaults .n_batch ; 1120 } 1121if (params .n_ubatch .empty ()) { 1122params .n_ubatch = cmd_params_defaults .n_ubatch ; 1123 } 1124if (params .type_k .empty ()) { 1125params .type_k = cmd_params_defaults .type_k ; 1126 } 1127if (params .type_v .empty ()) { 1128params .type_v = cmd_params_defaults .type_v ; 1129 } 1130if (params .n_gpu_layers .empty ()) { 1131params .n_gpu_layers = cmd_params_defaults .n_gpu_layers ; 1132 } 1133if (params .n_cpu_moe .empty ()) { 1134params .n_cpu_moe = cmd_params_defaults .n_cpu_moe ; 1135 } 1136if (params .split_mode .empty ()) { 1137params .split_mode = cmd_params_defaults .split_mode ; 1138 } 1139if (params .load_mode .empty ()) { 1140params .load_mode = cmd_params_defaults .load_mode ; 1141 } 1142if (params .lazy_mode .empty ()) { 1143params .lazy_mode = cmd_params_defaults .lazy_mode ; 1144 } 1145if (params .main_gpu .empty ()) { 1146params .main_gpu = cmd_params_defaults .main_gpu ; 1147 } 1148if (params .no_kv_offload .empty ()) { 1149params .no_kv_offload = cmd_params_defaults .no_kv_offload ; 1150 } 1151if (params .flash_attn .empty ()) { 1152params .flash_attn = cmd_params_defaults .flash_attn ; 1153 } 1154if (params .devices .empty ()) { 1155params .devices = cmd_params_defaults .devices ; 1156 } 1157if (params .tensor_split .empty ()) { 1158params .tensor_split = cmd_params_defaults .tensor_split ; 1159 } 1160if (params .tensor_buft_overrides .empty ()) { 1161params .tensor_buft_overrides = cmd_params_defaults .tensor_buft_overrides ; 1162 } 1163if (params .embeddings .empty ()) { 1164params .embeddings = cmd_params_defaults .embeddings ; 1165 } 1166if (params .no_op_offload .empty ()) { 1167params .no_op_offload = cmd_params_defaults .no_op_offload ; 1168 } 1169if (params .no_host .empty ()) { 1170params .no_host = cmd_params_defaults .no_host ; 1171 } 1172if (params .n_threads .empty ()) { 1173params .n_threads = cmd_params_defaults .n_threads ; 1174 } 1175if (params .cpu_mask .empty ()) { 1176params .cpu_mask = cmd_params_defaults .cpu_mask ; 1177 } 1178if (params .cpu_strict .empty ()) { 1179params .cpu_strict = cmd_params_defaults .cpu_strict ; 1180 } 1181if (params .poll .empty ()) { 1182params .poll = cmd_params_defaults .poll ; 1183 } 1184if (params .fit_params_target .empty ()) { 1185params .fit_params_target = cmd_params_defaults .fit_params_target ; 1186 } 1187if (params .fit_params_min_ctx .empty ()) { 1188params .fit_params_min_ctx = cmd_params_defaults .fit_params_min_ctx ; 1189 } 1190 1191return params ; 1192} 1193 1194struct cmd_params_instance { 1195 std::string model ; 1196int n_prompt ; 1197int n_gen ; 1198int n_depth ; 1199int n_batch ; 1200int n_ubatch ; 1201ggml_type type_k ; 1202ggml_type type_v ; 1203int n_threads ; 1204 std::string cpu_mask ; 1205bool cpu_strict ; 1206int poll ; 1207int n_gpu_layers ; 1208int n_cpu_moe ; 1209llama_split_mode split_mode ; 1210llama_load_mode load_mode ; 1211llama_lazy_mode lazy_mode ; 1212int main_gpu ; 1213bool no_kv_offload ; 1214llama_flash_attn_type flash_attn ; 1215 std::vector < ggml_backend_dev_t > devices ; 1216 std::vector < float > tensor_split ; 1217 std::vector < llama_model_tensor_buft_override > tensor_buft_overrides ; 1218bool embeddings ; 1219bool no_op_offload ; 1220bool no_host ; 1221size_t fit_target ; 1222uint32_t fit_min_ctx ; 1223 1224llama_model_params to_llama_mparams ()const { 1225llama_model_params mparams = llama_model_default_params (); 1226 1227mparams .n_gpu_layers = n_gpu_layers ; 1228if (!devices .empty ()) { 1229mparams .devices = const_cast < ggml_backend_dev_t *> (devices .data ()); 1230 } 1231mparams .split_mode = split_mode ; 1232mparams .load_mode = load_mode ; 1233mparams .lazy_mode = lazy_mode ; 1234mparams .main_gpu = main_gpu ; 1235mparams .tensor_split = tensor_split .data (); 1236mparams .no_host = no_host ; 1237 1238if (n_cpu_moe <=0 ) { 1239if (tensor_buft_overrides .empty ()) { 1240mparams .tensor_buft_overrides = nullptr ; 1241 }else { 1242GGML_ASSERT (tensor_buft_overrides .back ().pattern == nullptr && 1243"Tensor buffer overrides not terminated with empty pattern" ); 1244mparams .tensor_buft_overrides = tensor_buft_overrides .data (); 1245 } 1246 }else { 1247static std::vector < llama_model_tensor_buft_override > merged ; 1248static std::vector < std::string > patterns ; 1249 1250merged .clear (); 1251patterns .clear (); 1252 1253auto first = tensor_buft_overrides .begin (); 1254auto last = tensor_buft_overrides .end (); 1255if (first != last && (last - 1 )-> pattern == nullptr ) { 1256-- last ; 1257 } 1258merged .insert (merged .end (),first ,last ); 1259 1260patterns .reserve ((size_t )n_cpu_moe ); 1261merged .reserve (merged .size ()+ (size_t )n_cpu_moe + 1 ); 1262 1263for (int i = 0 ;i < n_cpu_moe ;++ i ) { 1264patterns .push_back (llm_ffn_block_regex (i ,LLM_FFN_EXPS_REGEX )); 1265merged .push_back ({patterns .back ().c_str (), 1266ggml_backend_cpu_buffer_type () }); 1267 } 1268 1269merged .push_back ({nullptr ,nullptr }); 1270 1271mparams .tensor_buft_overrides = merged .data (); 1272 } 1273 1274return mparams ; 1275 } 1276 1277bool equal_mparams (const cmd_params_instance & other )const { 1278return model == other .model && n_gpu_layers == other .n_gpu_layers && n_cpu_moe == other .n_cpu_moe && 1279split_mode == other .split_mode && 1280main_gpu == other .main_gpu && tensor_split == other .tensor_split && 1281load_mode == other .load_mode && lazy_mode == other .lazy_mode && 1282devices == other .devices && no_host == other .no_host && 1283vec_tensor_buft_override_equal (tensor_buft_overrides ,other .tensor_buft_overrides ); 1284 } 1285 1286llama_context_params to_llama_cparams ()const { 1287llama_context_params cparams = llama_context_default_params (); 1288 1289cparams .n_ctx = n_prompt + n_gen + n_depth ; 1290cparams .n_batch = n_batch ; 1291cparams .n_ubatch = n_ubatch ; 1292cparams .type_k = type_k ; 1293cparams .type_v = type_v ; 1294cparams .offload_kqv = !no_kv_offload ; 1295cparams .flash_attn_type = flash_attn ; 1296cparams .embeddings = embeddings ; 1297cparams .op_offload = !no_op_offload ; 1298cparams .swa_full = false; 1299 1300return cparams ; 1301 } 1302}; 1303 1304static std::vector < cmd_params_instance > get_cmd_params_instances (const cmd_params & params ) { 1305 std::vector < cmd_params_instance > instances ; 1306 1307// this ordering minimizes the number of times that each model needs to be reloaded 1308// clang-format off 1309for (const auto & m :params .model ) 1310for (const auto & fpt :params .fit_params_target ) 1311for (const auto & fpc :params .fit_params_min_ctx ) 1312for (const auto & nl :params .n_gpu_layers ) 1313for (const auto & ncmoe :params .n_cpu_moe ) 1314for (const auto & sm :params .split_mode ) 1315for (const auto & lm :params .load_mode ) 1316for (const auto & lzm :params .lazy_mode ) 1317for (const auto & mg :params .main_gpu ) 1318for (const auto & devs :params .devices ) 1319for (const auto & ts :params .tensor_split ) 1320for (const auto & ot :params .tensor_buft_overrides ) 1321for (const auto & noh :params .no_host ) 1322for (const auto & embd :params .embeddings ) 1323for (const auto & nopo :params .no_op_offload ) 1324for (const auto & nb :params .n_batch ) 1325for (const auto & nub :params .n_ubatch ) 1326for (const auto & tk :params .type_k ) 1327for (const auto & tv :params .type_v ) 1328for (const auto & nkvo :params .no_kv_offload ) 1329for (const auto & fa :params .flash_attn ) 1330for (const auto & nt :params .n_threads ) 1331for (const auto & cm :params .cpu_mask ) 1332for (const auto & cs :params .cpu_strict ) 1333for (const auto & nd :params .n_depth ) 1334for (const auto & pl :params .poll ) { 1335for (const auto & n_prompt :params .n_prompt ) { 1336if (n_prompt == 0 ) { 1337continue ; 1338 } 1339cmd_params_instance instance = { 1340/* .model = */ m , 1341/* .n_prompt = */ n_prompt , 1342/* .n_gen = */ 0 , 1343/* .n_depth = */ nd , 1344/* .n_batch = */ nb , 1345/* .n_ubatch = */ nub , 1346/* .type_k = */ tk , 1347/* .type_v = */ tv , 1348/* .n_threads = */ nt , 1349/* .cpu_mask = */ cm , 1350/* .cpu_strict = */ cs , 1351/* .poll = */ pl , 1352/* .n_gpu_layers = */ nl , 1353/* .n_cpu_moe = */ ncmoe , 1354/* .split_mode = */ sm , 1355/* .load_mode = */ lm , 1356/* .lazy_mode = */ lzm , 1357/* .main_gpu = */ mg , 1358/* .no_kv_offload = */ nkvo , 1359/* .flash_attn = */ fa , 1360/* .devices = */ devs , 1361/* .tensor_split = */ ts , 1362/* .tensor_buft_overrides = */ ot , 1363/* .embeddings = */ embd , 1364/* .no_op_offload = */ nopo , 1365/* .no_host = */ noh , 1366/* .fit_target = */ fpt , 1367/* .fit_min_ctx = */ fpc , 1368 }; 1369instances .push_back (instance ); 1370 } 1371 1372for (const auto & n_gen :params .n_gen ) { 1373if (n_gen == 0 ) { 1374continue ; 1375 } 1376cmd_params_instance instance = { 1377/* .model = */ m , 1378/* .n_prompt = */ 0 , 1379/* .n_gen = */ n_gen , 1380/* .n_depth = */ nd , 1381/* .n_batch = */ nb , 1382/* .n_ubatch = */ nub , 1383/* .type_k = */ tk , 1384/* .type_v = */ tv , 1385/* .n_threads = */ nt , 1386/* .cpu_mask = */ cm , 1387/* .cpu_strict = */ cs , 1388/* .poll = */ pl , 1389/* .n_gpu_layers = */ nl , 1390/* .n_cpu_moe = */ ncmoe , 1391/* .split_mode = */ sm , 1392/* .load_mode = */ lm , 1393/* .lazy_mode = */ lzm , 1394/* .main_gpu = */ mg , 1395/* .no_kv_offload = */ nkvo , 1396/* .flash_attn = */ fa , 1397/* .devices = */ devs , 1398/* .tensor_split = */ ts , 1399/* .tensor_buft_overrides = */ ot , 1400/* .embeddings = */ embd , 1401/* .no_op_offload = */ nopo , 1402/* .no_host = */ noh , 1403/* .fit_target = */ fpt , 1404/* .fit_min_ctx = */ fpc , 1405 }; 1406instances .push_back (instance ); 1407 } 1408 1409for (const auto & n_pg :params .n_pg ) { 1410if (n_pg .first == 0 && n_pg .second == 0 ) { 1411continue ; 1412 } 1413cmd_params_instance instance = { 1414/* .model = */ m , 1415/* .n_prompt = */ n_pg .first , 1416/* .n_gen = */ n_pg .second , 1417/* .n_depth = */ nd , 1418/* .n_batch = */ nb , 1419/* .n_ubatch = */ nub , 1420/* .type_k = */ tk , 1421/* .type_v = */ tv , 1422/* .n_threads = */ nt , 1423/* .cpu_mask = */ cm , 1424/* .cpu_strict = */ cs , 1425/* .poll = */ pl , 1426/* .n_gpu_layers = */ nl , 1427/* .n_cpu_moe = */ ncmoe , 1428/* .split_mode = */ sm , 1429/* .load_mode = */ lm , 1430/* .lazy_mode = */ lzm , 1431/* .main_gpu = */ mg , 1432/* .no_kv_offload = */ nkvo , 1433/* .flash_attn = */ fa , 1434/* .devices = */ devs , 1435/* .tensor_split = */ ts , 1436/* .tensor_buft_overrides = */ ot , 1437/* .embeddings = */ embd , 1438/* .no_op_offload = */ nopo , 1439/* .no_host = */ noh , 1440/* .fit_target = */ fpt , 1441/* .fit_min_ctx = */ fpc , 1442 }; 1443instances .push_back (instance ); 1444 } 1445 } 1446// clang-format on 1447 1448return instances ; 1449} 1450 1451struct test { 1452static const std::string build_commit ; 1453static const int build_number ; 1454const std::string cpu_info ; 1455const std::string gpu_info ; 1456 std::string model_filename ; 1457 std::string model_type ; 1458uint64_t model_size ; 1459uint64_t model_n_params ; 1460int n_batch ; 1461int n_ubatch ; 1462int n_threads ; 1463 std::string cpu_mask ; 1464bool cpu_strict ; 1465int poll ; 1466ggml_type type_k ; 1467ggml_type type_v ; 1468int n_gpu_layers ; 1469int n_cpu_moe ; 1470llama_split_mode split_mode ; 1471llama_load_mode load_mode ; 1472llama_lazy_mode lazy_mode ; 1473int main_gpu ; 1474bool no_kv_offload ; 1475llama_flash_attn_type flash_attn ; 1476 std::vector < ggml_backend_dev_t > devices ; 1477 std::vector < float > tensor_split ; 1478 std::vector < llama_model_tensor_buft_override > tensor_buft_overrides ; 1479bool embeddings ; 1480bool no_op_offload ; 1481bool no_host ; 1482size_t fit_target ; 1483uint32_t fit_min_ctx ; 1484int n_prompt ; 1485int n_gen ; 1486int n_depth ; 1487 std::string test_time ; 1488 std::vector < uint64_t > samples_ns ; 1489 1490test (const cmd_params_instance & inst ,const llama_model * lmodel ,const llama_context * ctx ) : 1491cpu_info (get_cpu_info ()), 1492gpu_info (get_gpu_info ()) { 1493 1494model_filename = inst .model ; 1495char buf [128 ]; 1496llama_model_desc (lmodel ,buf ,sizeof (buf )); 1497model_type = buf ; 1498model_size = llama_model_size (lmodel ); 1499model_n_params = llama_model_n_params (lmodel ); 1500n_batch = inst .n_batch ; 1501n_ubatch = inst .n_ubatch ; 1502n_threads = inst .n_threads ; 1503cpu_mask = inst .cpu_mask ; 1504cpu_strict = inst .cpu_strict ; 1505poll = inst .poll ; 1506type_k = inst .type_k ; 1507type_v = inst .type_v ; 1508n_gpu_layers = inst .n_gpu_layers ; 1509n_cpu_moe = inst .n_cpu_moe ; 1510split_mode = inst .split_mode ; 1511load_mode = inst .load_mode ; 1512lazy_mode = inst .lazy_mode ; 1513main_gpu = inst .main_gpu ; 1514no_kv_offload = inst .no_kv_offload ; 1515flash_attn = inst .flash_attn ; 1516devices = inst .devices ; 1517tensor_split = inst .tensor_split ; 1518tensor_buft_overrides = inst .tensor_buft_overrides ; 1519embeddings = inst .embeddings ; 1520no_op_offload = inst .no_op_offload ; 1521no_host = inst .no_host ; 1522fit_target = inst .fit_target ; 1523fit_min_ctx = inst .fit_min_ctx ; 1524n_prompt = inst .n_prompt ; 1525n_gen = inst .n_gen ; 1526n_depth = inst .n_depth ; 1527// RFC 3339 date-time format 1528time_t t = time (NULL ); 1529 std::strftime (buf ,sizeof (buf ),"%FT%TZ" ,gmtime (& t )); 1530test_time = buf ; 1531 1532 (void )ctx ; 1533 } 1534 1535uint64_t avg_ns ()const {return ::avg (samples_ns ); } 1536 1537uint64_t stdev_ns ()const {return ::stdev (samples_ns ); } 1538 1539 std::vector < double > get_ts ()const { 1540int n_tokens = n_prompt + n_gen ; 1541 std::vector < double > ts ; 1542 std::transform (samples_ns .begin (),samples_ns .end (), std::back_inserter (ts ), 1543 [n_tokens ](uint64_t t ) {return 1e9 * n_tokens /t ; }); 1544return ts ; 1545 } 1546 1547double avg_ts ()const {return ::avg (get_ts ()); } 1548 1549double stdev_ts ()const {return ::stdev (get_ts ()); } 1550 1551static std::string get_backend () { 1552 std::vector < std::string > backends ; 1553bool rpc_used = false; 1554for (size_t i = 0 ;i < ggml_backend_reg_count ();i ++ ) { 1555auto * reg = ggml_backend_reg_get (i ); 1556 std::string name = ggml_backend_reg_name (reg ); 1557if (string_starts_with (name ,"RPC" )) { 1558if (ggml_backend_reg_dev_count (reg )> 0 ) { 1559rpc_used = true; 1560 } 1561 }else { 1562if (name != "CPU" ) { 1563backends .push_back (ggml_backend_reg_name (reg )); 1564 } 1565 } 1566 } 1567if (rpc_used ) { 1568backends .push_back ("RPC" ); 1569 } 1570return backends .empty () ?"CPU" :join (backends ,"," ); 1571 } 1572 1573static const std::vector < std::string > & get_fields () { 1574static const std::vector < std::string > fields = { 1575"build_commit" ,"build_number" ,"cpu_info" ,"gpu_info" ,"backends" , 1576"model_filename" ,"model_type" ,"model_size" ,"model_n_params" ,"n_batch" , 1577"n_ubatch" ,"n_threads" ,"cpu_mask" ,"cpu_strict" ,"poll" , 1578"type_k" ,"type_v" ,"n_gpu_layers" ,"n_cpu_moe" ,"split_mode" , 1579"main_gpu" ,"no_kv_offload" ,"flash_attn" ,"devices" ,"tensor_split" , 1580"tensor_buft_overrides" ,"load_mode" ,"lazy_mode" , 1581"embeddings" , 1582"no_op_offload" ,"no_host" ,"fit_target" ,"fit_min_ctx" , 1583"n_prompt" ,"n_gen" ,"n_depth" , 1584"test_time" ,"avg_ns" ,"stddev_ns" ,"avg_ts" ,"stddev_ts" 1585 }; 1586return fields ; 1587 } 1588 1589enum field_type {STRING ,BOOL ,INT ,FLOAT }; 1590 1591static field_type get_field_type (const std::string & field ) { 1592if (field == "build_number" || field == "n_batch" || field == "n_ubatch" || field == "n_threads" || 1593field == "poll" || field == "model_size" || field == "model_n_params" || field == "n_gpu_layers" || 1594field == "main_gpu" || field == "n_prompt" || field == "n_gen" || field == "n_depth" || field == "avg_ns" || 1595field == "stddev_ns" || field == "no_op_offload" || field == "n_cpu_moe" || 1596field == "fit_target" || field == "fit_min_ctx" || field == "flash_attn" ) { 1597return INT ; 1598 } 1599if (field == "f16_kv" || field == "no_kv_offload" || field == "cpu_strict" || 1600field == "embeddings" || field == "no_host" ) { 1601return BOOL ; 1602 } 1603if (field == "avg_ts" || field == "stddev_ts" ) { 1604return FLOAT ; 1605 } 1606if (field == "load_mode" || field == "lazy_mode" ) { 1607return STRING ; 1608 } 1609return STRING ; 1610 } 1611 1612 std::vector < std::string > get_values ()const { 1613 std::string tensor_split_str ; 1614 std::string tensor_buft_overrides_str ; 1615int max_nonzero = 0 ; 1616for (size_t i = 0 ;i < llama_max_devices ();i ++ ) { 1617if (tensor_split [i ]> 0 ) { 1618max_nonzero = i ; 1619 } 1620 } 1621for (int i = 0 ;i <=max_nonzero ;i ++ ) { 1622char buf [32 ]; 1623snprintf (buf ,sizeof (buf ),"%.2f" ,tensor_split [i ]); 1624tensor_split_str += buf ; 1625if (i < max_nonzero ) { 1626tensor_split_str += "/" ; 1627 } 1628 } 1629if (tensor_buft_overrides .size ()== 1 ) { 1630// Last element of tensor_buft_overrides is always a null pattern 1631// so if it is only one element long, it must be a null pattern. 1632GGML_ASSERT (tensor_buft_overrides [0 ].pattern == nullptr ); 1633tensor_buft_overrides_str += "none" ; 1634 }else { 1635for (size_t i = 0 ;i < tensor_buft_overrides .size ()- 1 ;i ++ ) { 1636// Last element of tensor_buft_overrides is always a null pattern 1637if (tensor_buft_overrides [i ].pattern == nullptr ) { 1638tensor_buft_overrides_str += "none" ; 1639 }else { 1640tensor_buft_overrides_str += tensor_buft_overrides [i ].pattern ; 1641tensor_buft_overrides_str += "=" ; 1642tensor_buft_overrides_str += ggml_backend_buft_name (tensor_buft_overrides [i ].buft ); 1643 } 1644if (i + 2 < tensor_buft_overrides .size ()) { 1645tensor_buft_overrides_str += ";" ; 1646 } 1647 } 1648 } 1649 std::vector < std::string > values = {build_commit , 1650 std::to_string (build_number ), 1651cpu_info , 1652gpu_info , 1653get_backend (), 1654model_filename , 1655model_type , 1656 std::to_string (model_size ), 1657 std::to_string (model_n_params ), 1658 std::to_string (n_batch ), 1659 std::to_string (n_ubatch ), 1660 std::to_string (n_threads ), 1661cpu_mask , 1662 std::to_string (cpu_strict ), 1663 std::to_string (poll ), 1664ggml_type_name (type_k ), 1665ggml_type_name (type_v ), 1666 std::to_string (n_gpu_layers ), 1667 std::to_string (n_cpu_moe ), 1668split_mode_str (split_mode ), 1669 std::to_string (main_gpu ), 1670 std::to_string (no_kv_offload ), 1671 std::to_string ((int )flash_attn ), 1672devices_to_string (devices ), 1673tensor_split_str , 1674tensor_buft_overrides_str , 1675llama_load_mode_name (load_mode ), 1676lazy_mode_str (lazy_mode ), 1677 std::to_string (embeddings ), 1678 std::to_string (no_op_offload ), 1679 std::to_string (no_host ), 1680 std::to_string (fit_target ), 1681 std::to_string (fit_min_ctx ), 1682 std::to_string (n_prompt ), 1683 std::to_string (n_gen ), 1684 std::to_string (n_depth ), 1685test_time , 1686 std::to_string (avg_ns ()), 1687 std::to_string (stdev_ns ()), 1688 std::to_string (avg_ts ()), 1689 std::to_string (stdev_ts ()) }; 1690return values ; 1691 } 1692 1693 std::map < std::string , std::string > get_map ()const { 1694 std::map < std::string , std::string > map ; 1695auto fields = get_fields (); 1696auto values = get_values (); 1697 std::transform (fields .begin (),fields .end (),values .begin (), std::inserter (map ,map .end ()), 1698 std::make_pair < const std::string & ,const std::string &> ); 1699return map ; 1700 } 1701}; 1702 1703const std::string test::build_commit = llama_commit (); 1704const int test::build_number = llama_build_number (); 1705 1706struct printer { 1707virtual ~printer () {} 1708 1709FILE * fout ; 1710 1711virtual void print_header (const cmd_params & params ) { (void )params ; } 1712 1713virtual void print_test (const test & t )= 0 ; 1714 1715virtual void print_footer () {} 1716}; 1717 1718struct csv_printer :public printer { 1719static std::string escape_csv (const std::string & field ) { 1720 std::string escaped = "\"" ; 1721for (auto c :field ) { 1722if (c == '"' ) { 1723escaped += "\"" ; 1724 } 1725escaped += c ; 1726 } 1727escaped += "\"" ; 1728return escaped ; 1729 } 1730 1731void print_header (const cmd_params & params )override { 1732 std::vector < std::string > fields = test::get_fields (); 1733fprintf (fout ,"%s\n" ,join (fields ,"," ).c_str ()); 1734 (void )params ; 1735 } 1736 1737void print_test (const test & t )override { 1738 std::vector < std::string > values = t .get_values (); 1739 std::transform (values .begin (),values .end (),values .begin (),escape_csv ); 1740fprintf (fout ,"%s\n" ,join (values ,"," ).c_str ()); 1741 } 1742}; 1743 1744static std::string escape_json (const std::string & value ) { 1745 std::string escaped ; 1746for (auto c :value ) { 1747if (c == '"' ) { 1748escaped += "\\\"" ; 1749 }else if (c == '\\' ) { 1750escaped += "\\\\" ; 1751 }else if (c <=0x1f ) { 1752char buf [8 ]; 1753snprintf (buf ,sizeof (buf ),"\\u%04x" ,c ); 1754escaped += buf ; 1755 }else { 1756escaped += c ; 1757 } 1758 } 1759return escaped ; 1760} 1761 1762static std::string format_json_value (const std::string & field ,const std::string & value ) { 1763switch (test::get_field_type (field )) { 1764case test::STRING : 1765return "\"" + escape_json (value )+ "\"" ; 1766case test::BOOL : 1767return value == "0" ?"false" :"true" ; 1768default : 1769return value ; 1770 } 1771} 1772 1773struct json_printer :public printer { 1774bool first = true; 1775 1776void print_header (const cmd_params & params )override { 1777fprintf (fout ,"[\n" ); 1778 (void )params ; 1779 } 1780 1781void print_fields (const std::vector < std::string > & fields ,const std::vector < std::string > & values ) { 1782assert (fields .size ()== values .size ()); 1783for (size_t i = 0 ;i < fields .size ();i ++ ) { 1784fprintf (fout ," \"%s\": %s,\n" ,fields .at (i ).c_str (), 1785format_json_value (fields .at (i ),values .at (i )).c_str ()); 1786 } 1787 } 1788 1789void print_test (const test & t )override { 1790if (first ) { 1791first = false; 1792 }else { 1793fprintf (fout ,",\n" ); 1794 } 1795fprintf (fout ," {\n" ); 1796print_fields (test::get_fields (),t .get_values ()); 1797fprintf (fout ," \"samples_ns\": [ %s ],\n" ,join (t .samples_ns ,", " ).c_str ()); 1798fprintf (fout ," \"samples_ts\": [ %s ]\n" ,join (t .get_ts (),", " ).c_str ()); 1799fprintf (fout ," }" ); 1800fflush (fout ); 1801 } 1802 1803void print_footer ()override {fprintf (fout ,"\n]\n" ); } 1804}; 1805 1806struct jsonl_printer :public printer { 1807void print_fields (const std::vector < std::string > & fields ,const std::vector < std::string > & values ) { 1808assert (fields .size ()== values .size ()); 1809for (size_t i = 0 ;i < fields .size ();i ++ ) { 1810fprintf (fout ,"\"%s\": %s, " ,fields .at (i ).c_str (),format_json_value (fields .at (i ),values .at (i )).c_str ()); 1811 } 1812 } 1813 1814void print_test (const test & t )override { 1815fprintf (fout ,"{" ); 1816print_fields (test::get_fields (),t .get_values ()); 1817fprintf (fout ,"\"samples_ns\": [ %s ]," ,join (t .samples_ns ,", " ).c_str ()); 1818fprintf (fout ,"\"samples_ts\": [ %s ]" ,join (t .get_ts (),", " ).c_str ()); 1819fprintf (fout ,"}\n" ); 1820fflush (fout ); 1821 } 1822}; 1823 1824struct markdown_printer :public printer { 1825 std::vector < std::string > fields ; 1826 1827static int get_field_width (const std::string & field ) { 1828if (field == "model" ) { 1829return -30 ; 1830 } 1831if (field == "t/s" ) { 1832return 20 ; 1833 } 1834if (field == "size" || field == "params" ) { 1835return 10 ; 1836 } 1837if (field == "n_gpu_layers" ) { 1838return 3 ; 1839 } 1840if (field == "n_threads" ) { 1841return 7 ; 1842 } 1843if (field == "n_batch" ) { 1844return 7 ; 1845 } 1846if (field == "n_ubatch" ) { 1847return 8 ; 1848 } 1849if (field == "type_k" || field == "type_v" ) { 1850return 6 ; 1851 } 1852if (field == "split_mode" ) { 1853return 6 ; 1854 } 1855if (field == "load_mode" ) { 1856return 10 ; 1857 } 1858if (field == "flash_attn" ) { 1859return 3 ; 1860 } 1861if (field == "devices" ) { 1862return -12 ; 1863 } 1864if (field == "test" ) { 1865return 15 ; 1866 } 1867if (field == "no_op_offload" ) { 1868return 4 ; 1869 } 1870if (field == "no_host" ) { 1871return 4 ; 1872 } 1873 1874int width = std::max ((int )field .length (),10 ); 1875 1876if (test::get_field_type (field )== test::STRING ) { 1877return - width ; 1878 } 1879return width ; 1880 } 1881 1882static std::string get_field_display_name (const std::string & field ) { 1883if (field == "n_gpu_layers" ) { 1884return "ngl" ; 1885 } 1886if (field == "split_mode" ) { 1887return "sm" ; 1888 } 1889if (field == "n_threads" ) { 1890return "threads" ; 1891 } 1892if (field == "no_kv_offload" ) { 1893return "nkvo" ; 1894 } 1895if (field == "flash_attn" ) { 1896return "fa" ; 1897 } 1898if (field == "load_mode" ) { 1899return "lm" ; 1900 } 1901if (field == "embeddings" ) { 1902return "embd" ; 1903 } 1904if (field == "no_op_offload" ) { 1905return "nopo" ; 1906 } 1907if (field == "no_host" ) { 1908return "noh" ; 1909 } 1910if (field == "devices" ) { 1911return "dev" ; 1912 } 1913if (field == "tensor_split" ) { 1914return "ts" ; 1915 } 1916if (field == "tensor_buft_overrides" ) { 1917return "ot" ; 1918 } 1919if (field == "fit_target" ) { 1920return "fitt" ; 1921 } 1922if (field == "fit_min_ctx" ) { 1923return "fitc" ; 1924 } 1925return field ; 1926 } 1927 1928void print_header (const cmd_params & params )override { 1929// select fields to print 1930fields .emplace_back ("model" ); 1931fields .emplace_back ("size" ); 1932fields .emplace_back ("params" ); 1933fields .emplace_back ("backend" ); 1934bool is_cpu_backend = test::get_backend ().find ("CPU" )!= std::string::npos || 1935 test::get_backend ().find ("BLAS" )!= std::string::npos || 1936 test::get_backend ().find ("ZenDNN" )!= std::string::npos ; 1937if (!is_cpu_backend ) { 1938fields .emplace_back ("n_gpu_layers" ); 1939 } 1940if (params .n_cpu_moe .size ()> 1 || params .n_cpu_moe != cmd_params_defaults .n_cpu_moe ) { 1941fields .emplace_back ("n_cpu_moe" ); 1942 } 1943if (params .n_threads .size ()> 1 || params .n_threads != cmd_params_defaults .n_threads || is_cpu_backend ) { 1944fields .emplace_back ("n_threads" ); 1945 } 1946if (params .cpu_mask .size ()> 1 || params .cpu_mask != cmd_params_defaults .cpu_mask ) { 1947fields .emplace_back ("cpu_mask" ); 1948 } 1949if (params .cpu_strict .size ()> 1 || params .cpu_strict != cmd_params_defaults .cpu_strict ) { 1950fields .emplace_back ("cpu_strict" ); 1951 } 1952if (params .poll .size ()> 1 || params .poll != cmd_params_defaults .poll ) { 1953fields .emplace_back ("poll" ); 1954 } 1955if (params .n_batch .size ()> 1 || params .n_batch != cmd_params_defaults .n_batch ) { 1956fields .emplace_back ("n_batch" ); 1957 } 1958if (params .n_ubatch .size ()> 1 || params .n_ubatch != cmd_params_defaults .n_ubatch ) { 1959fields .emplace_back ("n_ubatch" ); 1960 } 1961if (params .type_k .size ()> 1 || params .type_k != cmd_params_defaults .type_k ) { 1962fields .emplace_back ("type_k" ); 1963 } 1964if (params .type_v .size ()> 1 || params .type_v != cmd_params_defaults .type_v ) { 1965fields .emplace_back ("type_v" ); 1966 } 1967if (params .main_gpu .size ()> 1 || params .main_gpu != cmd_params_defaults .main_gpu ) { 1968fields .emplace_back ("main_gpu" ); 1969 } 1970if (params .split_mode .size ()> 1 || params .split_mode != cmd_params_defaults .split_mode ) { 1971fields .emplace_back ("split_mode" ); 1972 } 1973if (params .no_kv_offload .size ()> 1 || params .no_kv_offload != cmd_params_defaults .no_kv_offload ) { 1974fields .emplace_back ("no_kv_offload" ); 1975 } 1976if (params .flash_attn .size ()> 1 || params .flash_attn != cmd_params_defaults .flash_attn ) { 1977fields .emplace_back ("flash_attn" ); 1978 } 1979if (params .devices .size ()> 1 || params .devices != cmd_params_defaults .devices ) { 1980fields .emplace_back ("devices" ); 1981 } 1982if (params .tensor_split .size ()> 1 || params .tensor_split != cmd_params_defaults .tensor_split ) { 1983fields .emplace_back ("tensor_split" ); 1984 } 1985if (params .tensor_buft_overrides .size ()> 1 || !vec_vec_tensor_buft_override_equal (params .tensor_buft_overrides ,cmd_params_defaults .tensor_buft_overrides )) { 1986fields .emplace_back ("tensor_buft_overrides" ); 1987 } 1988if (params .load_mode .size ()> 1 || params .load_mode != cmd_params_defaults .load_mode ) { 1989fields .emplace_back ("load_mode" ); 1990 } 1991if (params .lazy_mode .size ()> 1 || params .lazy_mode != cmd_params_defaults .lazy_mode ) { 1992fields .emplace_back ("lazy_mode" ); 1993 } 1994if (params .embeddings .size ()> 1 || params .embeddings != cmd_params_defaults .embeddings ) { 1995fields .emplace_back ("embeddings" ); 1996 } 1997if (params .no_op_offload .size ()> 1 || params .no_op_offload != cmd_params_defaults .no_op_offload ) { 1998fields .emplace_back ("no_op_offload" ); 1999 } 2000if (params .no_host .size ()> 1 || params .no_host != cmd_params_defaults .no_host ) { 2001fields .emplace_back ("no_host" ); 2002 } 2003if (params .fit_params_target .size ()> 1 || params .fit_params_target != cmd_params_defaults .fit_params_target ) { 2004fields .emplace_back ("fit_target" ); 2005 } 2006if (params .fit_params_min_ctx .size ()> 1 || params .fit_params_min_ctx != cmd_params_defaults .fit_params_min_ctx ) { 2007fields .emplace_back ("fit_min_ctx" ); 2008 } 2009fields .emplace_back ("test" ); 2010fields .emplace_back ("t/s" ); 2011 2012fprintf (fout ,"|" ); 2013for (const auto & field :fields ) { 2014fprintf (fout ," %*s |" ,get_field_width (field ),get_field_display_name (field ).c_str ()); 2015 } 2016fprintf (fout ,"\n" ); 2017fprintf (fout ,"|" ); 2018for (const auto & field :fields ) { 2019int width = get_field_width (field ); 2020fprintf (fout ," %s%s |" , std::string (std::abs (width )- 1 ,'-' ).c_str (),width > 0 ?":" :"-" ); 2021 } 2022fprintf (fout ,"\n" ); 2023 } 2024 2025void print_test (const test & t )override { 2026 std::map < std::string , std::string > vmap = t .get_map (); 2027 2028fprintf (fout ,"|" ); 2029for (const auto & field :fields ) { 2030 std::string value ; 2031char buf [128 ]; 2032if (field == "model" ) { 2033value = t .model_type ; 2034 }else if (field == "size" ) { 2035if (t .model_size < 1024 * 1024 * 1024 ) { 2036snprintf (buf ,sizeof (buf ),"%.2f MiB" ,t .model_size /1024.0 /1024.0 ); 2037 }else { 2038snprintf (buf ,sizeof (buf ),"%.2f GiB" ,t .model_size /1024.0 /1024.0 /1024.0 ); 2039 } 2040value = buf ; 2041 }else if (field == "params" ) { 2042if (t .model_n_params < 1000 * 1000 * 1000 ) { 2043snprintf (buf ,sizeof (buf ),"%.2f M" ,t .model_n_params /1e6 ); 2044 }else { 2045snprintf (buf ,sizeof (buf ),"%.2f B" ,t .model_n_params /1e9 ); 2046 } 2047value = buf ; 2048 }else if (field == "backend" ) { 2049value = test::get_backend (); 2050 }else if (field == "test" ) { 2051if (t .n_prompt > 0 && t .n_gen == 0 ) { 2052snprintf (buf ,sizeof (buf ),"pp%d" ,t .n_prompt ); 2053 }else if (t .n_gen > 0 && t .n_prompt == 0 ) { 2054snprintf (buf ,sizeof (buf ),"tg%d" ,t .n_gen ); 2055 }else { 2056snprintf (buf ,sizeof (buf ),"pp%d+tg%d" ,t .n_prompt ,t .n_gen ); 2057 } 2058if (t .n_depth > 0 ) { 2059int len = strlen (buf ); 2060snprintf (buf + len ,sizeof (buf )- len ," @ d%d" ,t .n_depth ); 2061 } 2062value = buf ; 2063 }else if (field == "t/s" ) { 2064snprintf (buf ,sizeof (buf ),"%.2f ± %.2f" ,t .avg_ts (),t .stdev_ts ()); 2065value = buf ; 2066 }else if (vmap .find (field )!= vmap .end ()) { 2067value = vmap .at (field ); 2068 }else { 2069assert (false); 2070exit (1 ); 2071 } 2072 2073int width = get_field_width (field ); 2074if (field == "t/s" ) { 2075// HACK: the utf-8 character is 2 bytes 2076width += 1 ; 2077 } 2078fprintf (fout ," %*s |" ,width ,value .c_str ()); 2079 } 2080fprintf (fout ,"\n" ); 2081 } 2082 2083void print_footer ()override { 2084fprintf (fout ,"\nbuild: %s (%d)\n" , test::build_commit .c_str (), test::build_number ); 2085 } 2086}; 2087 2088struct sql_printer :public printer { 2089static std::string get_sql_field_type (const std::string & field ) { 2090switch (test::get_field_type (field )) { 2091case test::STRING : 2092return "TEXT" ; 2093case test::BOOL : 2094case test::INT : 2095return "INTEGER" ; 2096case test::FLOAT : 2097return "REAL" ; 2098default : 2099assert (false); 2100exit (1 ); 2101 } 2102 } 2103 2104void print_header (const cmd_params & params )override { 2105 std::vector < std::string > fields = test::get_fields (); 2106fprintf (fout ,"CREATE TABLE IF NOT EXISTS llama_bench (\n" ); 2107for (size_t i = 0 ;i < fields .size ();i ++ ) { 2108fprintf (fout ," %s %s%s\n" ,fields .at (i ).c_str (),get_sql_field_type (fields .at (i )).c_str (), 2109i < fields .size ()- 1 ?"," :"" ); 2110 } 2111fprintf (fout ,");\n" ); 2112fprintf (fout ,"\n" ); 2113 (void )params ; 2114 } 2115 2116void print_test (const test & t )override { 2117fprintf (fout ,"INSERT INTO llama_bench (%s) " ,join (test::get_fields (),", " ).c_str ()); 2118fprintf (fout ,"VALUES (" ); 2119 std::vector < std::string > values = t .get_values (); 2120for (size_t i = 0 ;i < values .size ();i ++ ) { 2121fprintf (fout ,"'%s'%s" ,values .at (i ).c_str (),i < values .size ()- 1 ?", " :"" ); 2122 } 2123fprintf (fout ,");\n" ); 2124 } 2125}; 2126 2127struct ctx_state { 2128int depth = 0 ;// in tokens 2129 2130 std::vector < uint8_t > buf ;// the llama_context state buffer 2131}; 2132 2133static bool test_prompt (llama_context * ctx ,int n_prompt ,int n_batch ,int n_threads ) { 2134llama_set_n_threads (ctx ,n_threads ,n_threads ); 2135 2136const llama_model * model = llama_get_model (ctx ); 2137const llama_vocab * vocab = llama_model_get_vocab (model ); 2138const int32_t n_vocab = llama_vocab_n_tokens (vocab ); 2139 2140 std::vector < llama_token > tokens (n_batch ); 2141 2142int n_processed = 0 ; 2143 2144while (n_processed < n_prompt ) { 2145int n_tokens = std::min (n_prompt - n_processed ,n_batch ); 2146tokens [0 ]= n_processed == 0 && llama_vocab_get_add_bos (vocab ) ?llama_vocab_bos (vocab ) : std::rand () %n_vocab ; 2147for (int i = 1 ;i < n_tokens ;i ++ ) { 2148tokens [i ]= std::rand () %n_vocab ; 2149 } 2150int res = llama_decode (ctx ,llama_batch_get_one (tokens .data (),n_tokens )); 2151if (res != 0 ) { 2152fprintf (stderr ,"%s: failed to decode prompt batch, res = %d\n" ,__func__ ,res ); 2153return false; 2154 } 2155n_processed += n_tokens ; 2156 } 2157 2158llama_synchronize (ctx ); 2159return true; 2160} 2161 2162static bool test_gen (llama_context * ctx ,int n_gen ,int n_threads ) { 2163llama_set_n_threads (ctx ,n_threads ,n_threads ); 2164 2165const llama_model * model = llama_get_model (ctx ); 2166const llama_vocab * vocab = llama_model_get_vocab (model ); 2167const int32_t n_vocab = llama_vocab_n_tokens (vocab ); 2168 2169llama_token token = llama_vocab_get_add_bos (vocab ) ?llama_vocab_bos (vocab ) : std::rand () %n_vocab ; 2170 2171for (int i = 0 ;i < n_gen ;i ++ ) { 2172int res = llama_decode (ctx ,llama_batch_get_one (& token ,1 )); 2173if (res != 0 ) { 2174fprintf (stderr ,"%s: failed to decode generation batch, res = %d\n" ,__func__ ,res ); 2175return false; 2176 } 2177llama_synchronize (ctx ); 2178token = std::rand () %n_vocab ; 2179 } 2180return true; 2181} 2182 2183static void llama_null_log_callback (enum ggml_log_level level ,const char * text ,void * user_data ) { 2184 (void )level ; 2185 (void )text ; 2186 (void )user_data ; 2187} 2188 2189static std::unique_ptr < printer > create_printer (output_formats format ) { 2190switch (format ) { 2191case NONE : 2192return nullptr ; 2193case CSV : 2194return std::unique_ptr < printer > (new csv_printer ()); 2195case JSON : 2196return std::unique_ptr < printer > (new json_printer ()); 2197case JSONL : 2198return std::unique_ptr < printer > (new jsonl_printer ()); 2199case MARKDOWN : 2200return std::unique_ptr < printer > (new markdown_printer ()); 2201case SQL : 2202return std::unique_ptr < printer > (new sql_printer ()); 2203 } 2204GGML_ABORT ("fatal error" ); 2205} 2206 2207// satisfies -Wmissing-declarations 2208int llama_bench (int argc ,char ** argv ); 2209 2210int llama_bench (int argc ,char ** argv ) { 2211 std::setlocale (LC_NUMERIC ,"C" ); 2212// try to set locale for unicode characters in markdown 2213 std::setlocale (LC_CTYPE ,".UTF-8" ); 2214 2215#if !defined(NDEBUG ) 2216fprintf (stderr ,"warning: asserts enabled, performance may be affected\n" ); 2217#endif 2218 2219#if (defined(_MSC_VER )&& defined(_DEBUG ))|| (!defined(_MSC_VER )&& !defined(__OPTIMIZE__ )) 2220fprintf (stderr ,"warning: debug build, performance may be affected\n" ); 2221#endif 2222 2223#if defined(__SANITIZE_ADDRESS__ )|| defined(__SANITIZE_THREAD__ ) 2224fprintf (stderr ,"warning: sanitizer enabled, performance may be affected\n" ); 2225#endif 2226 2227// initialize backends 2228ggml_backend_load_all (); 2229 2230cmd_params params = parse_cmd_params (argc ,argv ); 2231 2232auto * cpu_dev = ggml_backend_dev_by_type (GGML_BACKEND_DEVICE_TYPE_CPU ); 2233if (!cpu_dev ) { 2234fprintf (stderr ,"%s: error: CPU backend is not loaded\n" ,__func__ ); 2235return 1 ; 2236 } 2237auto * cpu_reg = ggml_backend_dev_backend_reg (cpu_dev ); 2238auto * ggml_threadpool_new_fn = (decltype(ggml_threadpool_new )* )ggml_backend_reg_get_proc_address (cpu_reg ,"ggml_threadpool_new" ); 2239auto * ggml_threadpool_free_fn = (decltype(ggml_threadpool_free )* )ggml_backend_reg_get_proc_address (cpu_reg ,"ggml_threadpool_free" ); 2240 2241// initialize llama.cpp 2242if (!params .verbose ) { 2243llama_log_set (llama_null_log_callback ,NULL ); 2244 } 2245llama_backend_init (); 2246llama_numa_init (params .numa ); 2247 2248if (!set_process_priority (params .prio )) { 2249fprintf (stderr ,"%s: error: failed to set process priority\n" ,__func__ ); 2250return 1 ; 2251 } 2252 2253// initialize printer 2254 std::unique_ptr < printer > p = create_printer (params .output_format ); 2255 std::unique_ptr < printer > p_err = create_printer (params .output_format_stderr ); 2256 2257if (p ) { 2258p -> fout = stdout ; 2259p -> print_header (params ); 2260 } 2261 2262if (p_err ) { 2263p_err -> fout = stderr ; 2264p_err -> print_header (params ); 2265 } 2266 2267 std::vector < cmd_params_instance > params_instances = get_cmd_params_instances (params ); 2268 2269llama_model * lmodel = nullptr ; 2270const cmd_params_instance * prev_inst = nullptr ; 2271 2272// store the llama_context state at the previous depth that we performed a test 2273// ref: https://github.com/ggml-org/llama.cpp/pull/16944#issuecomment-3478151721 2274ctx_state cstate ; 2275 2276int params_idx = 0 ; 2277auto params_count = params_instances .size (); 2278for (const auto & inst :params_instances ) { 2279params_idx ++ ; 2280if (params .progress ) { 2281fprintf (stderr ,"llama-bench: benchmark %d/%zu: starting\n" ,params_idx ,params_count ); 2282 } 2283auto mparams = inst .to_llama_mparams (); 2284auto cparams = inst .to_llama_cparams (); 2285 2286bool do_fit = inst .fit_target != cmd_params_defaults .fit_params_target [0 ]|| 2287inst .fit_min_ctx != cmd_params_defaults .fit_params_min_ctx [0 ]; 2288 2289 std::vector < float > fit_tensor_split (llama_max_devices (),0.0f ); 2290 std::vector < llama_model_tensor_buft_override > fit_overrides (llama_max_tensor_buft_overrides (), {nullptr ,nullptr }); 2291 2292if (do_fit ) { 2293// free the previous model so fit sees full free VRAM 2294if (lmodel ) { 2295llama_model_free (lmodel ); 2296lmodel = nullptr ; 2297prev_inst = nullptr ; 2298 } 2299 2300// use default n_gpu_layers and n_ctx so common_fit_params can adjust them 2301mparams .n_gpu_layers = llama_model_default_params ().n_gpu_layers ; 2302mparams .tensor_split = fit_tensor_split .data (); 2303mparams .tensor_buft_overrides = fit_overrides .data (); 2304cparams .n_ctx = 0 ; 2305 2306 std::vector < size_t > margins (llama_max_devices (),inst .fit_target * 1024 * 1024 ); 2307 2308uint32_t n_ctx_needed = inst .n_prompt + inst .n_gen + inst .n_depth ; 2309cparams .n_ctx = std::max (cparams .n_ctx ,n_ctx_needed ); 2310 2311common_fit_params (inst .model .c_str (),& mparams ,& cparams , 2312fit_tensor_split .data (), 2313fit_overrides .data (), 2314margins .data (), 2315inst .fit_min_ctx , 2316nullptr , 2317params .verbose ?GGML_LOG_LEVEL_DEBUG :GGML_LOG_LEVEL_ERROR ); 2318 } 2319 2320// keep the same model between tests when possible 2321if (!lmodel || !prev_inst || !inst .equal_mparams (* prev_inst )) { 2322if (lmodel ) { 2323llama_model_free (lmodel ); 2324 } 2325 2326lmodel = llama_model_load_from_file (inst .model .c_str (),mparams ); 2327if (lmodel == NULL ) { 2328fprintf (stderr ,"%s: error: failed to load model '%s'\n" ,__func__ ,inst .model .c_str ()); 2329return 1 ; 2330 } 2331prev_inst = & inst ; 2332 } 2333 2334llama_context * ctx = llama_init_from_model (lmodel ,cparams ); 2335if (ctx == NULL ) { 2336fprintf (stderr ,"%s: error: failed to create context with model '%s'\n" ,__func__ ,inst .model .c_str ()); 2337llama_model_free (lmodel ); 2338return 1 ; 2339 } 2340 2341test t (inst ,lmodel ,ctx ); 2342 2343llama_memory_clear (llama_get_memory (ctx ), false); 2344 2345// cool off before the test 2346if (params .delay ) { 2347 std::this_thread::sleep_for (std::chrono::seconds (params .delay )); 2348 } 2349 2350struct ggml_threadpool_params tpp = ggml_threadpool_params_default (t .n_threads ); 2351if (!parse_cpu_mask (t .cpu_mask ,tpp .cpumask )) { 2352fprintf (stderr ,"%s: failed to parse cpu-mask: %s\n" ,__func__ ,t .cpu_mask .c_str ()); 2353llama_free (ctx ); 2354llama_model_free (lmodel ); 2355exit (1 ); 2356 } 2357tpp .strict_cpu = t .cpu_strict ; 2358tpp .poll = t .poll ; 2359tpp .prio = params .prio ; 2360 2361struct ggml_threadpool * threadpool = ggml_threadpool_new_fn (& tpp ); 2362if (!threadpool ) { 2363fprintf (stderr ,"%s: threadpool create failed : n_threads %d\n" ,__func__ ,tpp .n_threads ); 2364llama_free (ctx ); 2365llama_model_free (lmodel ); 2366exit (1 ); 2367 } 2368 2369llama_attach_threadpool (ctx ,threadpool ,NULL ); 2370 2371// warmup run 2372if (!params .no_warmup ) { 2373if (t .n_prompt > 0 ) { 2374if (params .progress ) { 2375fprintf (stderr ,"llama-bench: benchmark %d/%zu: warmup prompt run\n" ,params_idx ,params_count ); 2376 } 2377//test_prompt(ctx, std::min(t.n_batch, std::min(t.n_prompt, 32)), 0, t.n_batch, t.n_threads); 2378bool res = test_prompt (ctx ,t .n_prompt ,t .n_batch ,t .n_threads ); 2379if (!res ) { 2380fprintf (stderr ,"%s: error: failed to run prompt warmup\n" ,__func__ ); 2381llama_free (ctx ); 2382llama_model_free (lmodel ); 2383exit (1 ); 2384 } 2385 } 2386if (t .n_gen > 0 ) { 2387if (params .progress ) { 2388fprintf (stderr ,"llama-bench: benchmark %d/%zu: warmup generation run\n" ,params_idx ,params_count ); 2389 } 2390bool res = test_gen (ctx ,1 ,t .n_threads ); 2391if (!res ) { 2392fprintf (stderr ,"%s: error: failed to run gen warmup\n" ,__func__ ); 2393llama_free (ctx ); 2394llama_model_free (lmodel ); 2395exit (1 ); 2396 } 2397 } 2398 } 2399 2400for (int i = 0 ;i < params .reps ;i ++ ) { 2401llama_memory_clear (llama_get_memory (ctx ), false); 2402 2403if (t .n_depth > 0 ) { 2404bool is_cached = t .n_depth == cstate .depth ; 2405 2406if (is_cached ) { 2407// if previously we have computed at this depth, just restore the state 2408const size_t ret = llama_state_seq_set_data (ctx ,cstate .buf .data (),cstate .buf .size (),0 ); 2409if (ret == 0 ) { 2410// if the old state is incompatible with the current context - reprocess from scratch 2411is_cached = false; 2412 } 2413 } 2414 2415if (!is_cached ) { 2416if (params .progress ) { 2417fprintf (stderr ,"llama-bench: benchmark %d/%zu: depth run %d/%d\n" ,params_idx ,params_count , 2418i + 1 ,params .reps ); 2419 } 2420bool res = test_prompt (ctx ,t .n_depth ,t .n_batch ,t .n_threads ); 2421if (!res ) { 2422fprintf (stderr ,"%s: error: failed to run depth\n" ,__func__ ); 2423llama_free (ctx ); 2424llama_model_free (lmodel ); 2425exit (1 ); 2426 } 2427 2428// store the context state for reuse in later runs 2429cstate .depth = t .n_depth ; 2430cstate .buf .resize (llama_state_seq_get_size (ctx ,0 )); 2431llama_state_seq_get_data (ctx ,cstate .buf .data (),cstate .buf .size (),0 ); 2432 }else { 2433if (params .progress ) { 2434fprintf (stderr ,"llama-bench: benchmark %d/%zu: depth run %d/%d (cached)\n" ,params_idx ,params_count , 2435i + 1 ,params .reps ); 2436 } 2437 } 2438 } 2439 2440uint64_t t_start = get_time_ns (); 2441 2442if (t .n_prompt > 0 ) { 2443if (params .progress ) { 2444fprintf (stderr ,"llama-bench: benchmark %d/%zu: prompt run %d/%d\n" ,params_idx ,params_count , 2445i + 1 ,params .reps ); 2446 } 2447bool res = test_prompt (ctx ,t .n_prompt ,t .n_batch ,t .n_threads ); 2448if (!res ) { 2449fprintf (stderr ,"%s: error: failed to run prompt\n" ,__func__ ); 2450llama_free (ctx ); 2451llama_model_free (lmodel ); 2452exit (1 ); 2453 } 2454 } 2455if (t .n_gen > 0 ) { 2456if (params .progress ) { 2457fprintf (stderr ,"llama-bench: benchmark %d/%zu: generation run %d/%d\n" ,params_idx ,params_count , 2458i + 1 ,params .reps ); 2459 } 2460bool res = test_gen (ctx ,t .n_gen ,t .n_threads ); 2461if (!res ) { 2462fprintf (stderr ,"%s: error: failed to run gen\n" ,__func__ ); 2463llama_free (ctx ); 2464llama_model_free (lmodel ); 2465exit (1 ); 2466 } 2467 } 2468 2469uint64_t t_ns = get_time_ns ()- t_start ; 2470t .samples_ns .push_back (t_ns ); 2471 } 2472 2473if (p ) { 2474p -> print_test (t ); 2475fflush (p -> fout ); 2476 } 2477 2478if (p_err ) { 2479p_err -> print_test (t ); 2480fflush (p_err -> fout ); 2481 } 2482 2483llama_perf_context_print (ctx ); 2484 2485llama_free (ctx ); 2486 2487ggml_threadpool_free_fn (threadpool ); 2488 } 2489 2490llama_model_free (lmodel ); 2491 2492if (p ) { 2493p -> print_footer (); 2494 } 2495 2496if (p_err ) { 2497p_err -> print_footer (); 2498 } 2499 2500llama_backend_free (); 2501 2502return 0 ; 2503}