char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
7a4ca3cbd
char/aliceai-t5-moe
1#include "common.h" 2#include "llama.h" 3#include "ggml.h" 4 5#ifdef GGML_USE_CUDA 6#include "ggml-cuda.h" 7#endif 8 9#ifdef GGML_USE_METAL 10#include "ggml-metal.h" 11#endif 12 13#include <cstdio> 14#include <ctime> 15#include <random> 16#include <string> 17#include <vector> 18 19#define DEBUG_POS 5 20 21static void print_debug_tensor (struct ggml_tensor * t ,bool with_data = true) { 22printf ("%s: %s (%s): [%d, %d]\n" ,__func__ ,t -> name ,ggml_type_name (t -> type ), (int )t -> ne [0 ], (int )t -> ne [1 ]); 23if (!with_data )return ; 24printf ("%s: %s[0] = [" ,__func__ ,t -> name ); 25for (size_t i = 0 ;i <=DEBUG_POS ;i ++ ) { 26printf (" %f," ,ggml_get_f32_nd (t ,i ,0 ,0 ,0 )); 27 } 28printf (" ... ]\n" ); 29} 30 31namespace PCA { 32 33// input params for PCA computations 34struct pca_params { 35int n_threads = 1 ; 36int n_batch = 20 ;// number of iterations do to in one batch. larger the batch, more memory is used 37int n_iterations = 1000 ; 38float tolerance = 1e-7 ; 39 40// for debugging 41int i_layer = 0 ; 42int n_layers = 0 ; 43}; 44 45// result from each iteration 46struct pca_result { 47struct ggml_tensor * calculated_square = NULL ; 48 std::vector < struct ggml_tensor *> eigenvectors ; 49 std::vector < float > distances ; 50}; 51 52struct pca_model { 53ggml_backend_t backend = NULL ; 54ggml_backend_buffer_t buffer ; 55struct ggml_context * ctx ;// context to compute graph on target device 56struct ggml_context * ctx_host ;// host context to store results 57 58// tensors on target device 59struct ggml_tensor * dev_input ; 60struct ggml_tensor * dev_square ; 61struct ggml_tensor * dev_eigenvector ; 62 63pca_model (struct ggml_tensor * t_input ) { 64#ifdef GGML_USE_CUDA 65fprintf (stderr ,"%s: using CUDA backend\n" ,__func__ ); 66backend = ggml_backend_cuda_init (0 );// init device 0 67if (!backend ) { 68fprintf (stderr ,"%s: ggml_backend_cuda_init() failed\n" ,__func__ ); 69 } 70#endif 71 72// TODO: enable Metal support when support for GGML_OP_SQRT is added 73// #ifdef GGML_USE_METAL 74// fprintf(stderr, "%s: using Metal backend\n", __func__); 75// backend = ggml_backend_metal_init(); 76// if (!backend) { 77// fprintf(stderr, "%s: ggml_backend_metal_init() failed\n", __func__); 78// } 79// #endif 80 81// if there aren't GPU Backends fallback to CPU backend 82if (!backend ) { 83backend = ggml_backend_cpu_init (); 84 } 85 86const int num_tensors = 4 ; 87struct ggml_init_params params { 88/*.mem_size =*/ ggml_tensor_overhead ()* num_tensors , 89/*.mem_buffer =*/ NULL , 90/*.no_alloc =*/ true, 91 }; 92ctx = ggml_init (params ); 93 94auto n_samples = t_input -> ne [0 ]; 95auto n_embd = t_input -> ne [1 ]; 96 97dev_input = ggml_new_tensor_2d (ctx ,GGML_TYPE_F32 ,n_samples ,n_embd ); 98dev_square = ggml_new_tensor_2d (ctx ,GGML_TYPE_F32 ,n_embd ,n_embd ); 99dev_eigenvector = ggml_new_tensor_1d (ctx ,GGML_TYPE_F32 ,n_embd ); 100 101ggml_set_name (dev_input ,"dev_input" ); 102ggml_set_name (dev_square ,"dev_square" ); 103ggml_set_name (dev_eigenvector ,"dev_eigenvector" ); 104buffer = ggml_backend_alloc_ctx_tensors (ctx ,backend ); 105ggml_backend_tensor_set (dev_input ,t_input -> data ,0 ,ggml_nbytes (t_input )); 106 107// initialize eigenvector to random normalized vector 108 { 109 std::vector < float > random_vec (ggml_nelements (dev_eigenvector ),0.0 ); 110 std::default_random_engine generator (static_cast < unsigned int > (std::time (0 ))); 111 std::uniform_real_distribution < float > distribution (0.0 ,1.0 ); 112float sum_sqr = 0.0 ;// for normalizing random_vec 113for (size_t i = 0 ;i < random_vec .size ();++ i ) { 114float f = distribution (generator ); 115sum_sqr += f * f ; 116random_vec [i ]= f ; 117 } 118// normalize it 119float random_vec_norm = std::sqrt (sum_sqr ); 120for (size_t i = 0 ;i < random_vec .size ();++ i ) { 121random_vec [i ] /=random_vec_norm ; 122 } 123ggml_backend_tensor_set (dev_eigenvector ,random_vec .data (),0 ,ggml_nbytes (dev_eigenvector )); 124 } 125 } 126 127 ~pca_model () { 128ggml_free (ctx ); 129ggml_backend_buffer_free (buffer ); 130ggml_backend_free (backend ); 131 } 132}; 133 134static struct ggml_cgraph * build_graph_piter ( 135const struct pca_params & params , 136const pca_model & model , 137bool calc_square = false) { 138GGML_ASSERT (params .n_batch > 0 ); 139// TODO: buf_size must be able to scale with params.n_batch 140static size_t buf_size = ggml_tensor_overhead ()* GGML_DEFAULT_GRAPH_SIZE + ggml_graph_overhead (); 141static std::vector < uint8_t > buf (buf_size ); 142 143struct ggml_init_params params0 = { 144/*.mem_size =*/ buf_size , 145/*.mem_buffer =*/ buf .data (), 146/*.no_alloc =*/ true,// the tensors will be allocated later by ggml_allocr_alloc_graph() 147 }; 148// create a temporally context to build the graph 149struct ggml_context * ctx0 = ggml_init (params0 ); 150struct ggml_cgraph * gf = ggml_new_graph (ctx0 ); 151 152// turn v_diff_original into square matrix if needed 153struct ggml_tensor * tmp_square ; 154if (calc_square ) { 155tmp_square = ggml_mul_mat (ctx0 ,model .dev_input ,model .dev_input ); 156ggml_set_name (tmp_square ,"tmp_square" ); 157 } 158 159struct ggml_tensor * b_tensor ; 160struct ggml_tensor * distance ; 161struct ggml_tensor * old_eigen = model .dev_eigenvector ; 162struct ggml_tensor * input_square = calc_square ?tmp_square :model .dev_square ; 163 164for (int i = 0 ;i < params .n_batch ;++ i ) { 165// b_tensor = square * eigenvector^T 166b_tensor = ggml_mul_mat (ctx0 ,input_square ,old_eigen ); 167ggml_set_name (b_tensor ,"b_tensor" ); 168 169// normalize 170b_tensor = ggml_div_inplace (ctx0 , 171b_tensor , 172ggml_sqrt_inplace (ctx0 ,ggml_sum_rows (ctx0 ,ggml_sqr (ctx0 ,b_tensor ))) 173 ); 174ggml_format_name (b_tensor ,"b_tensor_norm_%d" ,i ); 175 176// calculate distance(new eigenvector - old eigenvector) 177// we don't use ggml_sub because it may not be implemented on GPU backend 178struct ggml_tensor * new_sub_old = ggml_add (ctx0 ,old_eigen ,ggml_scale (ctx0 ,b_tensor ,-1 )); 179distance = ggml_sqrt_inplace (ctx0 , 180ggml_sum_rows (ctx0 ,ggml_sqr_inplace (ctx0 ,new_sub_old ))); 181ggml_format_name (distance ,"distance_%d" ,i ); 182 183old_eigen = b_tensor ; 184 185// build operations nodes 186ggml_build_forward_expand (gf ,distance ); 187 } 188 189// delete the temporally context used to build the graph 190ggml_free (ctx0 ); 191return gf ; 192} 193 194static ggml_status compute_piter ( 195const struct pca_params & params , 196const pca_model & model , 197struct ggml_cgraph * gf , 198ggml_gallocr_t allocr , 199struct pca_result & result ) { 200// allocate tensors 201ggml_gallocr_alloc_graph (allocr ,gf ); 202 203if (ggml_backend_is_cpu (model .backend )) { 204ggml_backend_cpu_set_n_threads (model .backend ,params .n_threads ); 205 } 206 207ggml_status res = ggml_backend_graph_compute (model .backend ,gf ); 208if (res == GGML_STATUS_SUCCESS ) { 209auto extract_i = [](std::string prefix , std::string str )-> int { 210int i = -1 ; 211if (str .rfind (prefix ,0 )== 0 ) { 212sscanf (str .c_str (), (prefix + "%d" ).c_str (),& i ); 213 } 214return i ; 215 }; 216result .calculated_square = NULL ; 217result .eigenvectors .clear (); 218result .distances .clear (); 219result .eigenvectors .resize (params .n_batch ); 220result .distances .resize (params .n_batch ); 221// get output nodes 222for (int i = 0 ;i < ggml_graph_n_nodes (gf );++ i ) { 223auto node = ggml_graph_node (gf ,i ); 224int iter = -1 ; 225// find b_tensor (without copying data from device) 226if ((iter = extract_i ("b_tensor_norm_" ,node -> name ))> -1 ) { 227result .eigenvectors [iter ]= node ; 228 } 229// find distances, then copy data from device 230if ((iter = extract_i ("distance_" ,node -> name ))> -1 ) { 231float d ; 232ggml_backend_tensor_get (node ,& d ,0 ,sizeof (float )); 233result .distances [iter ]= d ; 234// std::cout << node->name << " = " << d << "\n"; 235 } 236// find tmp_square if it exists (without copying data from device) 237if (std::string (node -> name )== "tmp_square" ) { 238result .calculated_square = node ; 239 } 240 } 241 } 242return res ; 243} 244 245static void power_iteration ( 246const struct pca_params & params , 247struct ggml_tensor * input ,// shape of input: [n_samples, n_embd] 248struct ggml_tensor * output ) { 249//printf("in power iteration\n"); 250struct pca_model model (input ); 251 252ggml_gallocr_t allocr = ggml_gallocr_new (ggml_backend_get_default_buffer_type (model .backend )); 253struct pca_result result ; 254struct ggml_tensor * last_eigenvector = NULL ; 255 256int n_iters = params .n_iterations /params .n_batch ;// more batch, fewer iterations 257for (int iter = 0 ;iter < n_iters ;++ iter ) { 258bool calc_square = (iter == 0 );// only need to calculate square for first iteration 259struct ggml_cgraph * gf = build_graph_piter (params ,model ,calc_square ); 260// ggml_graph_dump_dot(gf, nullptr, "/tmp/_cgraph.dot"); 261compute_piter (params ,model ,gf ,allocr ,result ); 262 263for (size_t k = 0 ;k < result .distances .size ();++ k ) { 264last_eigenvector = result .eigenvectors [k ]; 265if (result .distances [k ]< params .tolerance ) { 266break ;// done 267 } 268 } 269 270if (calc_square ) { 271// copy and store the square matrix if needed 272GGML_ASSERT (result .calculated_square != NULL ); 273ggml_backend_tensor_copy (result .calculated_square ,model .dev_square ); 274 } 275 276 { 277// copy last eigen vector and store as input for next iteration 278GGML_ASSERT (last_eigenvector != NULL ); 279ggml_backend_tensor_copy (last_eigenvector ,model .dev_eigenvector ); 280 } 281 282printf ("%s: layer %d/%d, iteration: %d / total: %d (batch = %d) ...\n" , 283__func__ ,params .i_layer + 1 ,params .n_layers ,iter + 1 ,n_iters ,params .n_batch ); 284 } 285 286// get output tensor 287GGML_ASSERT (last_eigenvector ); 288ggml_backend_tensor_get (last_eigenvector ,output -> data ,0 ,ggml_nbytes (last_eigenvector )); 289//print_debug_tensor(output); 290ggml_gallocr_free (allocr ); 291 292// TODO @ngxson : The output vector is randomly inverted 293// Solution: https://github.com/ggml-org/llama.cpp/pull/8069#issuecomment-2185328171 294} 295 296static void run_pca ( 297struct pca_params & params , 298const std::vector < struct ggml_tensor *> & v_input ,// shape of v_input[0]: [n_samples, n_embd] 299const std::vector < struct ggml_tensor *> & v_output ) { 300printf ("%s: Running PCA...\n" ,__func__ ); 301for (size_t il = 0 ;il < v_input .size ();++ il ) { 302 303// prepare output vector 304struct ggml_tensor * ctrl_out = v_output [il ]; 305ggml_format_name (ctrl_out ,"direction.%zu" ,il + 1 ); 306 307// run power_iteration 308params .i_layer = il ; 309params .n_layers = v_input .size (); 310power_iteration (params ,v_input [il ],ctrl_out ); 311printf ("%s: Done layer %d / %d\n" ,__func__ , (int )il + 1 , (int )v_input .size ()); 312 } 313} 314 315}