char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
fdbd6abee
char/aliceai-t5-moe
1// thread safety test 2// - Loads a copy of the same model on each GPU, plus a copy on the CPU 3// - Creates n_parallel (--parallel) contexts per model 4// - Runs inference in parallel on each context 5 6#include <array> 7#include <thread> 8#include <vector> 9#include <atomic> 10#include "llama.h" 11#include "arg.h" 12#include "common.h" 13#include "log.h" 14#include "sampling.h" 15 16int main (int argc ,char ** argv ) { 17common_params params ; 18 19common_init (); 20 21if (!common_params_parse (argc ,argv ,params ,LLAMA_EXAMPLE_COMMON )) { 22return 1 ; 23 } 24 25llama_backend_init (); 26llama_numa_init (params .numa ); 27 28LOG_INF ("%s\n" ,common_params_get_system_info (params ).c_str ()); 29 30//llama_log_set([](ggml_log_level level, const char * text, void * /*user_data*/) { 31// if (level == GGML_LOG_LEVEL_ERROR) { 32// common_log_add(common_log_main(), level, "%s", text); 33// } 34//}, NULL); 35 36auto cparams = common_context_params_to_llama (params ); 37 38// each context has a single sequence 39cparams .n_seq_max = 1 ; 40 41int dev_count = ggml_backend_dev_count (); 42 std::vector < std::array < ggml_backend_dev_t ,2 >> gpus ; 43for (int i = 0 ;i < dev_count ;++ i ) { 44auto * dev = ggml_backend_dev_get (i ); 45if (dev && ggml_backend_dev_type (dev )== GGML_BACKEND_DEVICE_TYPE_GPU ) { 46gpus .push_back ({dev ,nullptr }); 47 } 48 } 49const int gpu_dev_count = (int )gpus .size (); 50const int num_models = gpu_dev_count + 1 + 1 ;// GPUs + 1 CPU model + 1 layer split 51//const int num_models = std::max(1, gpu_dev_count); 52const int num_contexts = std::max (1 ,params .n_parallel ); 53 54 std::vector < llama_model_ptr > models ; 55 std::vector < std::thread > threads ; 56 std::atomic < bool > failed = false; 57 58for (int m = 0 ;m < num_models ;++ m ) { 59auto mparams = common_model_params_to_llama (params ); 60 61if (m < gpu_dev_count ) { 62mparams .split_mode = LLAMA_SPLIT_MODE_NONE ; 63mparams .devices = gpus [m ].data (); 64 }else if (m == gpu_dev_count ) { 65mparams .split_mode = LLAMA_SPLIT_MODE_NONE ; 66mparams .main_gpu = -1 ;// CPU model 67 }else { 68mparams .split_mode = LLAMA_SPLIT_MODE_LAYER ; 69 } 70 71llama_model * model = llama_model_load_from_file (params .model .path .c_str (),mparams ); 72if (model == NULL ) { 73LOG_ERR ("%s: failed to load model '%s'\n" ,__func__ ,params .model .path .c_str ()); 74return 1 ; 75 } 76 77models .emplace_back (model ); 78 } 79 80for (int m = 0 ;m < num_models ;++ m ) { 81auto * model = models [m ].get (); 82for (int c = 0 ;c < num_contexts ;++ c ) { 83threads .emplace_back ([& ,m ,c ,model ]() { 84LOG_INF ("Creating context %d/%d for model %d/%d\n" ,c + 1 ,num_contexts ,m + 1 ,num_models ); 85 86llama_context_ptr ctx {llama_init_from_model (model ,cparams ) }; 87if (ctx == NULL ) { 88LOG_ERR ("failed to create context\n" ); 89failed .store (true); 90return ; 91 } 92 93 std::unique_ptr < common_sampler , decltype(& common_sampler_free )> sampler {common_sampler_init (model ,params .sampling ),common_sampler_free }; 94if (sampler == NULL ) { 95LOG_ERR ("failed to create sampler\n" ); 96failed .store (true); 97return ; 98 } 99 100llama_batch batch = {}; 101 { 102auto prompt = common_tokenize (ctx .get (),params .prompt , true); 103if (prompt .empty ()) { 104LOG_ERR ("failed to tokenize prompt\n" ); 105failed .store (true); 106return ; 107 } 108batch = llama_batch_get_one (prompt .data (),prompt .size ()); 109if (llama_decode (ctx .get (),batch )) { 110LOG_ERR ("failed to decode prompt\n" ); 111failed .store (true); 112return ; 113 } 114 } 115 116const auto * vocab = llama_model_get_vocab (model ); 117 std::string result = params .prompt ; 118 119for (int i = 0 ;i < params .n_predict ;i ++ ) { 120llama_token token ; 121if (batch .n_tokens > 0 ) { 122token = common_sampler_sample (sampler .get (),ctx .get (),batch .n_tokens - 1 ); 123 }else { 124token = llama_vocab_bos (vocab ); 125 } 126 127result += common_token_to_piece (ctx .get (),token ); 128 129if (llama_vocab_is_eog (vocab ,token )) { 130break ; 131 } 132 133batch = llama_batch_get_one (& token ,1 ); 134 135int ret = llama_decode (ctx .get (),batch ); 136if (ret == 1 && i > 0 ) { 137LOG_INF ("Context full, stopping generation.\n" ); 138break ; 139 } 140 141if (ret != 0 ) { 142LOG_ERR ("Model %d/%d, Context %d/%d: failed to decode\n" ,m + 1 ,num_models ,c + 1 ,num_contexts ); 143failed .store (true); 144return ; 145 } 146 } 147 148LOG_INF ("Model %d/%d, Context %d/%d: %s\n\n" ,m + 1 ,num_models ,c + 1 ,num_contexts ,result .c_str ()); 149 150llama_synchronize (ctx .get ()); 151 }); 152 } 153 } 154 155for (auto & thread :threads ) { 156thread .join (); 157 } 158 159if (failed ) { 160LOG_ERR ("One or more threads failed.\n" ); 161return 1 ; 162 } 163 164LOG_INF ("All threads finished without errors.\n" ); 165return 0 ; 166}