char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
680a9ae63
char/aliceai-t5-moe
1#include "llama.h" 2 3#include "build-info.h" 4#include "common.h" 5 6#include "../src/llama-model.h" 7 8#include "ggml.h" 9#include "ggml-cpu.h" 10 11#include <algorithm> 12#include <cassert> 13#include <cinttypes> 14#include <cmath> 15#include <cstdio> 16#include <cstring> 17#include <numeric> 18#include <regex> 19#include <string> 20#include <vector> 21#include <thread> 22#include <mutex> 23 24#if defined(_MSC_VER ) 25#pragma warning(disable: 4244 4267) // possible loss of data 26#endif 27 28struct quantize_stats_params { 29 std::string model = "models/7B/ggml-model-f16.gguf" ; 30bool verbose = false; 31bool per_layer_stats = false; 32bool print_histogram = false; 33bool reference = false; 34 std::vector < std::string > include_layers ; 35 std::vector < std::string > exclude_layers ; 36 std::vector < enum ggml_type > include_types ; 37}; 38 39constexpr size_t HISTOGRAM_BUCKETS = 150 ; 40constexpr double HISTOGRAM_RANGE = 0.03 ; 41 42struct error_stats { 43size_t num_samples ; 44double total_error ; 45double max_error ; 46uint64_t error_histogram [HISTOGRAM_BUCKETS ]; 47}; 48 49static void quantize_stats_print_usage (int /*argc*/ ,char ** argv ) { 50quantize_stats_params params ; 51fprintf (stderr ,"usage: %s [options]\n" ,argv [0 ]); 52fprintf (stderr ,"\n" ); 53fprintf (stderr ,"options:\n" ); 54fprintf (stderr ," -h, --help show this help message and exit\n" ); 55fprintf (stderr ," -m FNAME, --model FNAME\n" ); 56fprintf (stderr ," model path (default: %s)\n" ,params .model .c_str ()); 57fprintf (stderr ," -r, --reference\n" ); 58fprintf (stderr ," use reference implementation (default: false)\n" ); 59fprintf (stderr ," -v, --verbose\n" ); 60fprintf (stderr ," verbose output (default: false)\n" ); 61fprintf (stderr ," -p, --per-layer-stats\n" ); 62fprintf (stderr ," print stats per layer (default: false)\n" ); 63fprintf (stderr ," --histogram\n" ); 64fprintf (stderr ," print error histogram (default: false)\n" ); 65fprintf (stderr ," -l LAYER, --include-layer LAYER\n" ); 66fprintf (stderr ," only test layers matching pattern\n" ); 67fprintf (stderr ," -L LAYER, --exclude-layer LAYER\n" ); 68fprintf (stderr ," exclude layers matching pattern\n" ); 69fprintf (stderr ," -t TYPE, --type TYPE\n" ); 70fprintf (stderr ," only test given type (q4_0, q4_1)\n" ); 71fprintf (stderr ,"\n" ); 72} 73 74// Check if a layer is included/excluded by command line 75static bool layer_included (const quantize_stats_params & params ,const std::string & layer ) { 76for (const auto & excluded :params .exclude_layers ) { 77if (std::regex_search (layer , std::regex (excluded ))) { 78return false; 79 } 80 } 81for (const auto & included :params .include_layers ) { 82if (std::regex_search (layer , std::regex (included ))) { 83return true; 84 } 85 } 86return params .include_layers .empty (); 87} 88 89// Update error statistics given vectors with the before/after result of quantization 90static void update_error_stats (int64_t nelements ,const float * input ,const float * output ,error_stats & stats ) { 91for (int64_t i = 0 ;i < nelements ;i ++ ) { 92double diff = input [i ]- output [i ]; 93stats .total_error += diff * diff ; 94stats .max_error = fmax (fabs (diff ),stats .max_error ); 95stats .error_histogram [std::max (std::min ((size_t )floor (fabs (diff ) /HISTOGRAM_RANGE * HISTOGRAM_BUCKETS ),HISTOGRAM_BUCKETS - 1 ), (size_t )0 )]++ ; 96 } 97stats .num_samples += nelements ; 98} 99 100static void combine_error_stats (error_stats & into ,const error_stats & from ) { 101into .num_samples += from .num_samples ; 102into .total_error += from .total_error ; 103if (from .max_error > into .max_error )into .max_error = from .max_error ; 104for (size_t i = 0 ;i < HISTOGRAM_BUCKETS ;++ i )into .error_histogram [i ]+= from .error_histogram [i ]; 105} 106 107static double find_quantile (const error_stats & stats ,double quantile ) { 108double sum = std::accumulate (std::begin (stats .error_histogram ), std::end (stats .error_histogram ),0.0 ); 109 110double accum = 0 ; 111for (size_t i = 0 ;i < HISTOGRAM_BUCKETS ;i ++ ) { 112accum += stats .error_histogram [i ]; 113if (accum >=sum * quantile ) { 114return (i + 1 )* HISTOGRAM_RANGE /HISTOGRAM_BUCKETS ; 115 } 116 } 117return INFINITY ; 118} 119 120static void print_error_stats (const std::string & name ,const error_stats & stats ,bool print_histogram ) { 121double rmse = sqrt (stats .total_error / (double )stats .num_samples ); 122double median = find_quantile (stats ,.5 ); 123double pct95 = find_quantile (stats ,.95 ); 124printf ("%-50s: rmse %.8f, maxerr %.8f, 95pct<%.4f, median<%.4f\n" ,name .c_str (),rmse ,stats .max_error ,pct95 ,median ); 125if (print_histogram ) { 126printf ("Error distribution:\n" ); 127for (size_t i = 0 ;i < HISTOGRAM_BUCKETS ;i ++ ) { 128double lower = i * HISTOGRAM_RANGE /HISTOGRAM_BUCKETS ; 129double upper = (i + 1 )* HISTOGRAM_RANGE /HISTOGRAM_BUCKETS ; 130if (i == HISTOGRAM_BUCKETS - 1 )upper = INFINITY ; 131printf ("[%3.4f, %3.4f): %11" PRIu64 "\n" ,lower ,upper ,stats .error_histogram [i ]); 132 } 133 } 134} 135 136// copied from ggml.h - verify that we can access this as a flat array 137static bool tensor_is_contiguous (const struct ggml_tensor * tensor ) { 138 static_assert(GGML_MAX_DIMS == 4 ,"GGML_MAX_DIMS is not 4 - update this function" ); 139 140return 141tensor -> nb [0 ]== ggml_type_size (tensor -> type )&& 142tensor -> nb [1 ]== (tensor -> nb [0 ]* tensor -> ne [0 ])/ggml_blck_size (tensor -> type )&& 143tensor -> nb [2 ]== tensor -> nb [1 ]* tensor -> ne [1 ]&& 144tensor -> nb [3 ]== tensor -> nb [2 ]* tensor -> ne [2 ]; 145} 146 147static void test_roundtrip_on_chunk ( 148const ggml_tensor * layer ,int64_t offset ,int64_t chunk_size ,const ggml_type_traits & qfns ,const ggml_type_traits_cpu & qfns_cpu ,bool use_reference , 149float * input_scratch ,char * quantized_scratch ,float * output_scratch ,error_stats & stats 150) { 151if (layer -> type == GGML_TYPE_F16 ) { 152for (int i = 0 ;i < chunk_size ;i ++ ) { 153input_scratch [i ]= ggml_get_f32_1d (layer ,i + offset ); 154 } 155 }else { 156input_scratch = ggml_get_data_f32 (layer )+ offset ; 157 } 158 159if (use_reference ) { 160qfns .from_float_ref (input_scratch ,quantized_scratch ,chunk_size ); 161 }else { 162qfns_cpu .from_float (input_scratch ,quantized_scratch ,chunk_size ); 163 } 164qfns .to_float (quantized_scratch ,output_scratch ,chunk_size ); 165 166update_error_stats (chunk_size ,input_scratch ,output_scratch ,stats ); 167} 168 169 170// Run quantization function for a single layer and update error stats 171static void test_roundtrip_on_layer ( 172 std::string & name ,bool print_layer_stats ,const ggml_type_traits & qfns ,const ggml_type_traits_cpu & qfns_cpu ,bool use_reference , 173const ggml_tensor * layer , std::vector < float > & input_scratch , std::vector < char > & quantized_scratch , 174 std::vector < float > & output_scratch ,error_stats & total_error ,int max_thread = 0 175) { 176assert (tensor_is_contiguous (layer )); 177error_stats layer_error {}; 178uint64_t nelements = ggml_nelements (layer ); 179 180float * input_scratch_ptr = nullptr ; 181if (layer -> type == GGML_TYPE_F16 ) { 182if (input_scratch .size ()< nelements )input_scratch .resize (nelements ); 183input_scratch_ptr = input_scratch .data (); 184 } 185if (quantized_scratch .size ()< 4 * nelements )quantized_scratch .resize (4 * nelements ); 186if (output_scratch .size ()< nelements )output_scratch .resize (nelements ); 187 188if (max_thread < 1 )max_thread = std::thread::hardware_concurrency (); 189int chunk_size = 32 * 512 ; 190int num_chunks = (nelements + chunk_size - 1 )/chunk_size ; 191 192if (num_chunks < 2 || max_thread < 2 ) { 193test_roundtrip_on_chunk (layer ,0 ,nelements ,qfns ,qfns_cpu ,use_reference ,input_scratch_ptr ,quantized_scratch .data (), 194output_scratch .data (),print_layer_stats ?layer_error :total_error ); 195 }else { 196auto & stats = print_layer_stats ?layer_error :total_error ; 197 std::mutex mutex ; 198uint64_t counter = 0 ; 199auto compute = [& mutex ,& counter ,& stats ,& qfns ,& qfns_cpu ,nelements ,layer ,use_reference ,input_scratch_ptr , 200& quantized_scratch ,& output_scratch ,chunk_size ] () { 201error_stats local_stats {}; 202while (true) { 203 std::unique_lock < std::mutex > lock (mutex ); 204uint64_t offset = counter ;counter += chunk_size ; 205if (offset >=nelements ) { 206combine_error_stats (stats ,local_stats ); 207break ; 208 } 209lock .unlock (); 210uint64_t chunk = offset + chunk_size < nelements ?chunk_size :nelements - offset ; 211test_roundtrip_on_chunk (layer ,offset ,chunk ,qfns ,qfns_cpu ,use_reference ,input_scratch_ptr + offset , 212quantized_scratch .data ()+ 4 * offset ,output_scratch .data ()+ offset ,local_stats ); 213 } 214 }; 215int nthread = std::min (num_chunks ,max_thread ); 216 std::vector < std::thread > workers (nthread - 1 ); 217for (auto & w :workers )w = std::thread (compute ); 218compute (); 219for (auto & w :workers )w .join (); 220 } 221 222if (print_layer_stats ) { 223print_error_stats (name ,layer_error , false); 224combine_error_stats (total_error ,layer_error ); 225 } 226} 227 228int main (int argc ,char ** argv ) { 229ggml_time_init (); 230 231quantize_stats_params params ; 232 233// read command line 234 235int max_thread = 0 ; 236bool invalid_param = false; 237 std::string arg ; 238for (int i = 1 ;i < argc ;i ++ ) { 239arg = argv [i ]; 240 241if (arg == "-h" || arg == "--help" ) { 242quantize_stats_print_usage (argc ,argv ); 243exit (0 ); 244 }else if (arg == "-r" || arg == "--reference" ) { 245params .reference = true; 246 }else if (arg == "-v" ) { 247params .verbose = true; 248 }else if (arg == "-p" || arg == "--per-layer-stats" ) { 249params .per_layer_stats = true; 250 }else if (arg == "--histogram" ) { 251params .print_histogram = true; 252 }else if (arg == "-m" || arg == "--model" ) { 253if (++ i >=argc ) { 254invalid_param = true; 255break ; 256 } 257params .model = argv [i ]; 258 }else if (arg == "-l" || arg == "--include-layer" ) { 259if (++ i >=argc ) { 260invalid_param = true; 261break ; 262 } 263params .include_layers .emplace_back (argv [i ]); 264 }else if (arg == "-L" || arg == "--exclude-layer" ) { 265if (++ i >=argc ) { 266invalid_param = true; 267break ; 268 } 269params .exclude_layers .emplace_back (argv [i ]); 270 }else if (arg == "-t" || arg == "--type" ) { 271if (++ i >=argc ) { 272invalid_param = true; 273break ; 274 } 275int j ; 276for (j = 0 ;j < GGML_TYPE_COUNT ;++ j ) { 277const auto * name = ggml_type_name ((ggml_type )j ); 278if (name && strcmp (argv [i ],name )== 0 )break ; 279 } 280if (j < GGML_TYPE_COUNT ) { 281params .include_types .push_back ((ggml_type )j ); 282 }else { 283fprintf (stderr ,"error: %s not in list of types\n" ,argv [i ]); 284invalid_param = true; 285 } 286 }else if (arg == "-n" || arg == "--num-threads" ) { 287if (++ i >=argc ) { 288invalid_param = true; 289break ; 290 } 291max_thread = atoi (argv [i ]); 292 }else { 293fprintf (stderr ,"error: unknown argument: %s\n" ,arg .c_str ()); 294quantize_stats_print_usage (argc ,argv ); 295return 1 ; 296 } 297 } 298if (invalid_param ) { 299fprintf (stderr ,"error: invalid parameter for argument: %s\n" ,arg .c_str ()); 300quantize_stats_print_usage (argc ,argv ); 301return 1 ; 302 } 303 304llama_print_build_info (llama_version ()); 305 306// load the model 307fprintf (stderr ,"Loading model\n" ); 308 309const int64_t t_main_start_us = ggml_time_us (); 310llama_model * model ; 311llama_context * ctx ; 312 313 { 314auto mparams = llama_model_default_params (); 315mparams .load_mode = LLAMA_LOAD_MODE_NONE ; 316 317model = llama_model_load_from_file (params .model .c_str (),mparams ); 318 319if (model == NULL ) { 320fprintf (stderr ,"%s: error: failed to load model '%s'\n" ,__func__ ,params .model .c_str ()); 321return 1 ; 322 } 323 324auto cparams = llama_context_default_params (); 325cparams .n_ctx = 256 ; 326 327ctx = llama_init_from_model (model ,cparams ); 328 329if (ctx == NULL ) { 330fprintf (stderr ,"%s: error: failed to create context with model '%s'\n" ,__func__ ,params .model .c_str ()); 331llama_model_free (model ); 332return 1 ; 333 } 334 } 335 336const auto & tensors = llama_internal_get_tensor_map (model ); 337 338// check layer tensors 339int included_layers = 0 ; 340int64_t max_nelements = 0 ; 341bool is_f16 = false; 342for (const auto & kv_tensor :tensors ) { 343if (!layer_included (params ,kv_tensor .first )) { 344continue ; 345 } 346if (params .verbose ) { 347printf ("%s: type %s, size %" PRId64 "\n" ,kv_tensor .first .c_str (),ggml_type_name (kv_tensor .second -> type ),ggml_nelements (kv_tensor .second )); 348 } 349if (kv_tensor .second -> type == GGML_TYPE_F16 ) { 350is_f16 = true; 351 }else if (kv_tensor .second -> type != GGML_TYPE_F32 ) { 352fprintf (stderr ,"%s: error: Quantization should be tested with a float model, " 353"this model contains already quantized layers (%s is type %d)\n" ,__func__ ,kv_tensor .first .c_str (),kv_tensor .second -> type ); 354llama_free (ctx ); 355llama_model_free (model ); 356return 1 ; 357 } 358included_layers ++ ; 359max_nelements = std::max (max_nelements ,ggml_nelements (kv_tensor .second )); 360 } 361 362if (is_f16 ) { 363printf ("note: source model is f16\n" ); 364 } 365printf ("testing %d layers with max size %" PRId64 "\n" ,included_layers ,max_nelements ); 366// allocate scratch space 367 std::vector < float > input_scratch ; 368 std::vector < char > quantized_scratch ; 369 std::vector < float > output_scratch ; 370 371// loop throught quantization types 372for (int i = 0 ;i < GGML_TYPE_COUNT ;i ++ ) { 373const ggml_type type = (ggml_type )i ; 374if (!params .include_types .empty ()&& std::find (params .include_types .begin (),params .include_types .end (),i )== params .include_types .end ()) { 375continue ; 376 } 377const auto * qfns = ggml_get_type_traits (type ); 378const auto * qfns_cpu = ggml_get_type_traits_cpu (type ); 379if (qfns_cpu -> from_float && qfns -> to_float ) { 380if (params .verbose ) { 381printf ("testing %s ...\n" ,ggml_type_name (type )); 382 } 383 384ggml_quantize_init (type ); 385 386error_stats global_stats {}; 387 388for (const auto & kv_tensor :tensors ) { 389if (!layer_included (params ,kv_tensor .first )) { 390continue ; 391 } 392if (params .verbose ) { 393printf (" %s ...\n" ,kv_tensor .first .c_str ()); 394 } 395 std::string layer_name {ggml_type_name (type ) }; 396layer_name += "::" + kv_tensor .first ; 397test_roundtrip_on_layer ( 398layer_name , 399params .per_layer_stats , 400* qfns ,* qfns_cpu , 401params .reference , 402kv_tensor .second , 403input_scratch , 404quantized_scratch , 405output_scratch , 406global_stats , 407max_thread 408 ); 409 } 410 411print_error_stats (ggml_type_name (type ),global_stats ,params .print_histogram ); 412 } 413 } 414 415 416llama_free (ctx ); 417llama_model_free (model ); 418// report timing 419 { 420const int64_t t_main_end_us = ggml_time_us (); 421 422printf ("\n" ); 423printf ("%s: total time = %8.2f ms\n" ,__func__ , (t_main_end_us - t_main_start_us )/1000.0 ); 424 } 425 426return 0 ; 427}