char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
bee378e09
char/aliceai-t5-moe
1// Benchmark quantization specific functions on synthetic data 2 3#include "ggml.h" 4#include "ggml-cpu.h" 5 6#undef NDEBUG 7#include <algorithm> 8#include <assert.h> 9#include <functional> 10#include <math.h> 11#include <memory> 12#include <stdio.h> 13#include <string> 14#include <vector> 15 16#if defined(_MSC_VER ) 17#pragma warning(disable: 4244 4267) // possible loss of data 18#endif 19 20#define MAX_ALIGNMENT 64 21#define QK 32 22#define WARMUP 5 23#define ITERATIONS 10 24#define MAX_ITERATIONS 100000000 25 26#define L1_SIZE 32*128 27#define L2_SIZE 32*2048 28#define L3_SIZE 32*20480 29#define MEM_SIZE 32*2048000 30 31struct quantize_perf_params { 32 std::vector < std::string > include_types ; 33 std::vector < size_t > test_sizes ; 34size_t alignment_offset = 0 ; 35bool op_quantize_row_q_reference = false; 36bool op_quantize_row_q = false; 37bool op_dequantize_row_q = false; 38bool op_quantize_row_q_dot = false; 39bool op_vec_dot_q = false; 40int64_t iterations = ITERATIONS ; 41}; 42 43#if defined(__x86_64__ )|| defined(__i386__ ) 44 45#include <x86intrin.h> 46inline int64_t cpu_cycles () { 47// Rough way to detect new-ish CPUs 48#ifdef __POPCNT__ 49unsigned int dummy ; 50return __rdtscp (& dummy ); 51#else 52return __rdtsc (); 53#endif 54} 55 56#else 57 58#define cpu_cycles () 0 59 60#endif 61 62 63// Generate synthetic data 64static void generate_data (float offset ,size_t n ,float * dst ) { 65for (size_t i = 0 ;i < n ;i ++ ) { 66dst [i ]= 0.1 + 2 * cosf (i + offset ); 67 } 68} 69 70static float gigabytes_per_second (size_t bytes ,int64_t usecs ) { 71return bytes / (float )usecs * 1000000 / (1024 * 1024 * 1024 ); 72} 73 74static void * align_with_offset (void * ptr ,int offset ) { 75size_t dummy_size = MAX_ALIGNMENT * 4 ; 76return (char * ) std::align (MAX_ALIGNMENT ,MAX_ALIGNMENT ,ptr ,dummy_size )+ offset ; 77} 78 79static void benchmark_function (size_t size ,size_t q_size ,int64_t iterations ,const std::function < float (void )> & func ) { 80int64_t min_time_us = INT64_MAX ; 81int64_t total_time_us = 0 ; 82int64_t min_time_cycles = INT64_MAX ; 83int64_t total_time_cycles = 0 ; 84 85for (int i = 0 ;i < WARMUP ;i ++ ) { 86func (); 87 } 88 89for (int i = 0 ;i < iterations ;i ++ ) { 90const int64_t start_time = ggml_time_us (); 91const int64_t start_cycles = cpu_cycles (); 92 93func (); 94 95const int64_t end_cycles = cpu_cycles (); 96const int64_t end_time = ggml_time_us (); 97 98total_time_cycles += end_cycles - start_cycles ; 99min_time_cycles = std::min (min_time_cycles ,end_cycles - start_cycles ); 100total_time_us += end_time - start_time ; 101min_time_us = std::min (min_time_us ,end_time - start_time ); 102 } 103 104printf (" min cycles/%d vals : %9.2f\n" ,QK ,QK * min_time_cycles / (float )size ); 105printf (" avg cycles/%d vals : %9.2f\n" ,QK ,QK * total_time_cycles / (float ) (size * iterations )); 106printf (" float32 throughput : %9.2f GB/s\n" ,gigabytes_per_second (4 * size * iterations ,total_time_us )); 107printf (" quantized throughput : %9.2f GB/s\n" ,gigabytes_per_second (q_size * iterations ,total_time_us )); 108} 109 110static void usage (char * argv []) { 111printf ("Benchmark quantization specific functions on synthetic data\n" ); 112printf ("\n" ); 113printf ("usage: %s [options]\n" ,argv [0 ]); 114printf ("\n" ); 115printf ("options: (default)\n" ); 116printf (" -h, --help show this help message and exit\n" ); 117printf (" --size SIZE set test size, divisible by 32 (L1_SIZE:%d)\n" ,L1_SIZE ); 118printf (" -3 use size as L1, L2, L3 sizes (L1:%d L2:%d L3:%d)\n" ,L1_SIZE ,L2_SIZE ,L3_SIZE ); 119printf (" -4 use size as L1, L2, L3, MEM sizes (L1:%d L2:%d L3:%d MEM:%d)\n" ,L1_SIZE ,L2_SIZE ,L3_SIZE ,MEM_SIZE ); 120printf (" --op OP set test operation as quantize_row_q_reference, quantize_row_q, dequantize_row_q,\n" ); 121printf (" quantize_row_q_dot, vec_dot_q (all)\n" ); 122printf (" --type TYPE set test type as" ); 123for (int i = 0 ;i < GGML_TYPE_COUNT ;i ++ ) { 124ggml_type type = (ggml_type )i ; 125const auto * qfns = ggml_get_type_traits (type ); 126const auto * qfns_cpu = ggml_get_type_traits_cpu (type ); 127if (ggml_type_name (type )!= NULL ) { 128if (qfns_cpu -> from_float && qfns -> to_float ) { 129printf (" %s" ,ggml_type_name (type )); 130 } 131 } 132 } 133printf (" (all)\n" ); 134printf (" --alignment-offset OFFSET\n" ); 135printf (" set alignment offset as OFFSET (0)\n" ); 136printf (" -i NUM, --iterations NUM\n" ); 137printf (" set test iteration number (%d)\n" ,ITERATIONS ); 138} 139 140int main (int argc ,char * argv []) { 141quantize_perf_params params {}; 142 143// read command line 144 145bool invalid_param = false; 146 std::string arg ; 147for (int i = 1 ;i < argc ;i ++ ) { 148arg = argv [i ]; 149 150if (arg == "--size" ) { 151if (++ i >=argc ) { 152invalid_param = true; 153break ; 154 } 155size_t size = std::stoi (argv [i ]); 156if (size %32 != 0 ) { 157fprintf (stderr ,"error: size %zu not divisible by 32\n" ,size ); 158invalid_param = true; 159break ; 160 } 161params .test_sizes .push_back (size ); 162 }else if (arg == "-3" ) { 163// quick select sizes that probably fit in CPU caches 164params .test_sizes .push_back (L1_SIZE ); 165params .test_sizes .push_back (L2_SIZE ); 166params .test_sizes .push_back (L3_SIZE ); 167 }else if (arg == "-4" ) { 168// quick select cache sizes + memory 169params .test_sizes .push_back (L1_SIZE ); 170params .test_sizes .push_back (L2_SIZE ); 171params .test_sizes .push_back (L3_SIZE ); 172params .test_sizes .push_back (MEM_SIZE ); 173 }else if (arg == "--op" ) { 174if (++ i >=argc ) { 175invalid_param = true; 176break ; 177 } 178 std::string op {argv [i ]}; 179if (op == "quantize_row_q_reference" ) { 180params .op_quantize_row_q_reference = true; 181 }else if (op == "quantize_row_q" ) { 182params .op_quantize_row_q = true; 183 }else if (op == "dequantize_row_q" ) { 184params .op_dequantize_row_q = true; 185 }else if (op == "quantize_row_q_dot" ) { 186params .op_quantize_row_q_dot = true; 187 }else if (op == "vec_dot_q" ) { 188params .op_vec_dot_q = true; 189 }else { 190invalid_param = true; 191break ; 192 } 193 }else if (arg == "--type" ) { 194if (++ i >=argc ) { 195invalid_param = true; 196break ; 197 } 198params .include_types .push_back (argv [i ]); 199 }else if (arg == "--alignment-offset" ) { 200if (++ i >=argc ) { 201invalid_param = true; 202break ; 203 } 204int alignment = std::stoi (argv [i ]); 205if (alignment < 0 || alignment > MAX_ALIGNMENT ) { 206fprintf (stderr ,"error: alignment-offset must be less than %d\n" ,MAX_ALIGNMENT ); 207invalid_param = true; 208break ; 209 } 210params .alignment_offset = alignment ; 211 }else if ((arg == "-i" )|| (arg == "--iterations" )) { 212if (++ i >=argc ) { 213invalid_param = true; 214break ; 215 } 216int number = std::stoi (argv [i ]); 217if (number < 0 || number > MAX_ITERATIONS ) { 218fprintf (stderr ,"error: iterations must be less than %d\n" ,MAX_ITERATIONS ); 219invalid_param = true; 220break ; 221 } 222params .iterations = number ; 223 }else if ((arg == "-h" )|| (arg == "--help" )) { 224usage (argv ); 225return 1 ; 226 }else { 227fprintf (stderr ,"error: unknown argument: %s\n" ,arg .c_str ()); 228return 1 ; 229 } 230 } 231if (invalid_param ) { 232fprintf (stderr ,"error: invalid parameter for argument: %s\n" ,arg .c_str ()); 233return 1 ; 234 } 235 236if (params .test_sizes .empty ()) { 237params .test_sizes .push_back (L1_SIZE ); 238 } 239if (!(params .op_quantize_row_q_reference || params .op_quantize_row_q || params .op_dequantize_row_q || params .op_quantize_row_q_dot || params .op_vec_dot_q )) { 240params .op_quantize_row_q_reference = params .op_quantize_row_q = params .op_dequantize_row_q = params .op_quantize_row_q_dot = params .op_vec_dot_q = true; 241 } 242 243 std::sort (params .test_sizes .begin (),params .test_sizes .end ()); 244size_t largest = params .test_sizes .back (); 245 246 std::vector < uint8_t > test_data1_v (largest * 4 + MAX_ALIGNMENT * 2 ); 247 std::vector < uint8_t > test_data2_v (largest * 4 + MAX_ALIGNMENT * 2 ); 248 std::vector < uint8_t > test_q1_v (largest * 4 + MAX_ALIGNMENT * 2 ); 249 std::vector < uint8_t > test_q2_v (largest * 4 + MAX_ALIGNMENT * 2 ); 250 std::vector < uint8_t > test_out_v (largest * 4 + MAX_ALIGNMENT * 2 ); 251 252float * test_data1 = (float * )align_with_offset (test_data1_v .data (),params .alignment_offset ); 253float * test_data2 = (float * )align_with_offset (test_data2_v .data (),params .alignment_offset ); 254float * test_q1 = (float * )align_with_offset (test_q1_v .data (),params .alignment_offset ); 255float * test_q2 = (float * )align_with_offset (test_q2_v .data (),params .alignment_offset ); 256float * test_out = (float * )align_with_offset (test_out_v .data (),params .alignment_offset ); 257 258generate_data (0 ,largest ,test_data1 ); 259generate_data (1 ,largest ,test_data2 ); 260 261int64_t iterations = params .iterations ; 262 263ggml_cpu_init (); 264 265for (int i = 0 ;i < GGML_TYPE_COUNT ;i ++ ) { 266ggml_type type = (ggml_type )i ; 267const auto * qfns = ggml_get_type_traits (type ); 268const auto * qfns_cpu = ggml_get_type_traits_cpu (type ); 269if (!params .include_types .empty ()&& ggml_type_name (type )&& std::find (params .include_types .begin (),params .include_types .end (),ggml_type_name (type ))== params .include_types .end ()) { 270continue ; 271 } 272 273if (qfns_cpu -> from_float && qfns -> to_float ) { 274printf ("%s\n" ,ggml_type_name (type )); 275 276ggml_quantize_init (type ); 277 278if (params .op_quantize_row_q_reference ) { 279printf (" quantize_row_q_reference\n" ); 280for (size_t size :params .test_sizes ) { 281printf (" %zu values (%.2f MB)\n" ,size ,4 * size /(float )(1024 * 1024 )); 282auto quantize_fn = [& ](void )-> float { 283qfns -> from_float_ref (test_data1 ,test_q1 ,size ); 284return test_q1 [0 ]; 285 }; 286size_t quantized_size = ggml_row_size (type ,size ); 287benchmark_function (size ,quantized_size ,iterations ,quantize_fn ); 288 } 289printf ("\n" ); 290 } 291 292if (params .op_quantize_row_q ) { 293printf (" quantize_row_q\n" ); 294for (size_t size :params .test_sizes ) { 295printf (" %zu values (%.2f MB)\n" ,size ,4 * size /(float )(1024 * 1024 )); 296auto quantize_fn = [& ](void )-> float { 297qfns_cpu -> from_float (test_data1 ,test_q1 ,size ); 298return test_q1 [0 ]; 299 }; 300size_t quantized_size = ggml_row_size (type ,size ); 301benchmark_function (size ,quantized_size ,iterations ,quantize_fn ); 302 } 303printf ("\n" ); 304 } 305 306if (params .op_dequantize_row_q ) { 307printf (" dequantize_row_q\n" ); 308qfns_cpu -> from_float (test_data1 ,test_q1 ,largest ); 309for (size_t size :params .test_sizes ) { 310printf (" %zu values (%.2f MB)\n" ,size ,4 * size /(float )(1024 * 1024 )); 311auto quantize_fn = [& ](void )-> float { 312qfns -> to_float (test_q1 ,test_out ,size ); 313return test_out [0 ]; 314 }; 315size_t quantized_size = ggml_row_size (type ,size ); 316benchmark_function (size ,quantized_size ,iterations ,quantize_fn ); 317 } 318printf ("\n" ); 319 } 320 321if (params .op_quantize_row_q_dot ) { 322printf (" quantize_row_q_dot\n" ); 323for (size_t size :params .test_sizes ) { 324printf (" %zu values (%.2f MB)\n" ,size ,4 * size /(float )(1024 * 1024 )); 325auto quantize_fn = [& ](void )-> float { 326const auto * vdot = ggml_get_type_traits_cpu (qfns_cpu -> vec_dot_type ); 327vdot -> from_float (test_data1 ,test_q1 ,size ); 328return test_q1 [0 ]; 329 }; 330size_t quantized_size = ggml_row_size (type ,size ); 331benchmark_function (size ,quantized_size ,iterations ,quantize_fn ); 332 } 333printf ("\n" ); 334 } 335 336if (params .op_vec_dot_q ) { 337printf (" vec_dot_q\n" ); 338qfns_cpu -> from_float (test_data1 ,test_q1 ,largest ); 339qfns_cpu -> from_float (test_data2 ,test_q2 ,largest ); 340for (size_t size :params .test_sizes ) { 341printf (" %zu values (%.2f MB)\n" ,size ,4 * size /(float )(1024 * 1024 )); 342auto quantize_fn = [& ](void )-> float { 343float result ; 344qfns_cpu -> vec_dot (size ,& result ,0 ,test_q1 ,0 ,test_q2 ,0 ,1 ); 345return result ; 346 }; 347size_t quantized_size = ggml_row_size (type ,size ); 348benchmark_function (size ,quantized_size ,iterations ,quantize_fn ); 349 } 350printf ("\n" ); 351 } 352 } 353 } 354 355return 0 ; 356}