char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
81b0d882a
char/aliceai-t5-moe
1#include "ime_env.h" 2 3#include "ggml-impl.h" 4#include "spine_mem_pool.h" 5 6#include <fcntl.h> 7#include <unistd.h> 8 9#include <algorithm> 10#include <array> 11#include <cctype> 12#include <fstream> 13#include <string> 14#include <thread> 15#include <unordered_map> 16 17namespace ggml::cpu::riscv64_spacemit { 18bool spine_core_info::get_spine_core_info (std::vector < spine_core_info > & result ) { 19static std::unordered_map < uint64_t ,spine_core_arch_id > spine_march_mapping_ = { 20 {0x8000000058000001 , spine_core_arch_id::core_arch_x60 }, 21 {0x8000000041000001 , spine_core_arch_id::core_arch_a60 }, 22 {0x8000000058000002 , spine_core_arch_id::core_arch_x100 }, 23 {0x8000000041000002 , spine_core_arch_id::core_arch_a100 }, 24 }; 25 26result .clear (); 27 std::ifstream file ("/proc/cpuinfo" ); 28 std::string line ; 29 30 std::vector < std::array < uint64_t ,2 >> cpu_info_list ; 31 32uint64_t current_processor = spine_invalid_core_id ; 33uint64_t current_marchid = 0 ; 34bool has_processor = false; 35bool has_marchid = false; 36 37if (!file .is_open ()) { 38return false; 39 } 40 41while (std::getline (file ,line )) { 42if (line .substr (0 ,9 )== "processor" ) { 43if (has_processor && has_marchid ) { 44cpu_info_list .push_back ({current_processor ,current_marchid }); 45 } 46 47size_t colon_pos = line .find (':' ); 48if (colon_pos != std::string::npos ) { 49current_processor = std::stoi (line .substr (colon_pos + 1 )); 50has_processor = true; 51 } 52 53has_marchid = false; 54 }else if (line .substr (0 ,7 )== "marchid" ) { 55size_t colon_pos = line .find (':' ); 56if (colon_pos != std::string::npos ) { 57 std::string marchid_str = line .substr (colon_pos + 1 ); 58marchid_str .erase (std::remove_if (marchid_str .begin (),marchid_str .end (),isspace ),marchid_str .end ()); 59current_marchid = std::stoull (marchid_str ,nullptr ,16 ); 60has_marchid = true; 61 } 62 } 63 } 64 65if (has_processor && has_marchid ) { 66cpu_info_list .push_back ({current_processor ,current_marchid }); 67 } 68 69if (has_processor && has_marchid ) { 70for (auto & cpu_info :cpu_info_list ) { 71if (cpu_info [0 ]!= spine_invalid_core_id && 72spine_march_mapping_ .find (cpu_info [1 ])!= spine_march_mapping_ .end ()) { 73auto core_info = spine_core_info (); 74core_info .core_id = cpu_info [0 ]; 75core_info .arch_id = spine_core_arch_id (spine_march_mapping_ [cpu_info [1 ]]); 76 77result .push_back (core_info ); 78 } 79 } 80 } 81 82return has_processor && has_marchid ; 83} 84 85namespace { 86uint16_t hex_string_to_u16 (const std::string & hex_str ) { 87try { 88size_t pos = 0 ; 89if (hex_str .substr (0 ,2 )== "0x" || hex_str .substr (0 ,2 )== "0X" ) { 90pos = 2 ; 91 } 92unsigned long result = std::stoul (hex_str .substr (pos ),nullptr ,16 ); 93if (result > std::numeric_limits < uint16_t > ::max ()) { 94throw std::out_of_range ("Converted value is out of range for uint16_t" ); 95 } 96return static_cast < uint16_t > (result ); 97 }catch (const std::invalid_argument & e ) { 98throw std::invalid_argument ("Invalid hexadecimal string" ); 99 }catch (const std::out_of_range & e ) { 100throw ; 101 } 102} 103 104const char * spine_mem_pool_backend_to_string (spine_mem_pool_backend backend ) { 105switch (backend ) { 106case spine_mem_pool_backend::none : 107return "NONE" ; 108case spine_mem_pool_backend::posix_memalign : 109return "POSIX" ; 110case spine_mem_pool_backend::transparent_hugepage : 111return "HPAGE" ; 112case spine_mem_pool_backend::hugetlb_1g : 113return "HPAGE1GB" ; 114 } 115 116return "unknown" ; 117} 118 119spine_mem_pool_backend parse_mem_backend (const char * mem_backend_str ) { 120if (mem_backend_str == nullptr || mem_backend_str [0 ]== '\0' ) { 121return spine_mem_pool_backend::transparent_hugepage ; 122 } 123 124 std::string value (mem_backend_str ); 125 std::transform (value .begin (),value .end (),value .begin (), 126 [](unsigned char ch ) {return static_cast < char > (std::tolower (ch )); }); 127 128if (value == "none" ) { 129return spine_mem_pool_backend::none ; 130 } 131 132if (value == "posix" ) { 133return spine_mem_pool_backend::posix_memalign ; 134 } 135 136if (value == "hpage" ) { 137return spine_mem_pool_backend::transparent_hugepage ; 138 } 139 140if (value == "hpage1gb" ) { 141return spine_mem_pool_backend::hugetlb_1g ; 142 } 143 144throw std::runtime_error ("invalid SPACEMIT_MEM_BACKEND: " + value + ", expected NONE, POSIX, HPAGE or HPAGE1GB" ); 145} 146}// namespace 147 148spine_env_info::spine_env_info () { 149num_cores = static_cast < int > (std::thread::hardware_concurrency ()); 150 spine_core_info::get_spine_core_info (core_info_list ); 151 152// special for x60 K1 153if (core_info_list .size ()== 8 && core_info_list [0 ].arch_id == spine_core_arch_id::core_arch_x60 ) { 154for (int i = 0 ;i < 4 ;i ++ ) { 155core_info_list [i ].arch_id = spine_core_arch_id::core_arch_a60 ; 156 } 157 } 158 159// special for qemu 160if (core_info_list .size ()== 0 ) { 161char * spine_core_arch_str = getenv ("SPACEMIT_CORE_ARCH" ); 162if (spine_core_arch_str != nullptr ) { 163auto arch_id = hex_string_to_u16 (spine_core_arch_str ); 164for (int i = 0 ;i < num_cores ;i ++ ) { 165auto core_info = spine_core_info (); 166core_info .core_id = i ; 167core_info .arch_id = spine_core_arch_id {arch_id }; 168core_info_list .push_back (core_info ); 169 } 170 } 171 } 172 173if (core_info_list .size ()== 0 ) { 174throw std::runtime_error ( 175"Failed to get SPACEMIT_CORE_ARCH from environment or failed to parse it from /proc/cpuinfo" ); 176 } 177 178char * spine_perfer_core_arch_str = getenv ("SPACEMIT_PERFER_CORE_ARCH" ); 179if (spine_perfer_core_arch_str != nullptr && spine_perfer_core_arch_str != "" ) { 180perfer_core_arch_id = spine_core_arch_id {hex_string_to_u16 (spine_perfer_core_arch_str ) }; 181 } 182 183char * spine_perfer_core_id_str = getenv ("SPACEMIT_PERFER_CORE_ID" ); 184 std::vector < int > perfer_core_id_vec ; 185if (spine_perfer_core_id_str != nullptr && spine_perfer_core_id_str != "" ) { 186 std::string perfer_core_id_str (spine_perfer_core_id_str ); 187size_t start = 0 ; 188size_t end = 0 ; 189while ((end = perfer_core_id_str .find (',' ,start ))!= std::string::npos ) { 190 std::string core_id_substr = perfer_core_id_str .substr (start ,end - start ); 191perfer_core_id_vec .push_back (std::stoi (core_id_substr )); 192start = end + 1 ; 193 } 194 std::string core_id_substr = perfer_core_id_str .substr (start ); 195perfer_core_id_vec .push_back (std::stoi (core_id_substr )); 196 } 197 198perfer_core_ids .reserve (num_cores ); 199if (perfer_core_arch_id == spine_core_arch_id::core_arch_none ) { 200for (auto & core_info :core_info_list ) { 201auto core_arch_id = core_info .arch_id ; 202auto core_arch_head = (uint16_t ) (core_arch_id ) >>12 ; 203if (core_arch_head == 0xA ) { 204num_perfer_cores ++ ; 205perfer_core_arch_id = core_arch_id ; 206cpu_mask |= (1ULL <<core_info .core_id ); 207perfer_core_ids .push_back (core_info .core_id ); 208 } 209 } 210 }else { 211for (auto & core_info :core_info_list ) { 212auto core_arch_id = core_info .arch_id ; 213if (core_arch_id == perfer_core_arch_id ) { 214num_perfer_cores ++ ; 215cpu_mask |= (1ULL <<core_info .core_id ); 216 217auto core_arch_head = (uint16_t ) (core_arch_id ) >>12 ; 218if (core_arch_head == 0xA ) { 219perfer_core_ids .push_back (core_info .core_id ); 220 } 221 } 222 } 223if (num_perfer_cores == 0 ) { 224GGML_ABORT ("can not find core with arch id %x for SPACEMIT_PERFER_CORE_ARCH in core info list\n" , 225 (uint16_t )perfer_core_arch_id ); 226 } 227 } 228 229if (perfer_core_id_vec .size ()> 0 ) { 230perfer_core_ids .clear (); 231cpu_mask = 0 ; 232num_perfer_cores = 0 ; 233for (int core_id :perfer_core_id_vec ) { 234if (core_id < 0 || core_id >=num_cores ) { 235GGML_ABORT ("invalid core id in SPACEMIT_PERFER_CORE_ID: %d, should be between 0 and %d\n" ,core_id , 236num_cores - 1 ); 237 } 238auto core_info = core_info_list [core_id ]; 239auto core_arch_id = core_info .arch_id ; 240if (core_arch_id == perfer_core_arch_id ) { 241cpu_mask |= (1ULL <<core_id ); 242perfer_core_ids .push_back (core_id ); 243 }else { 244GGML_ABORT ( 245"core id %d in SPACEMIT_PERFER_CORE_ID has arch id %x which does not match " 246"SPACEMIT_PERFER_CORE_ARCH %x\n" , 247core_id , (uint16_t )core_arch_id , (uint16_t )perfer_core_arch_id ); 248 } 249 } 250 std::string perfer_core_id_vec_str ; 251for (int core_id :perfer_core_id_vec ) { 252perfer_core_id_vec_str += std::to_string (core_id )+ "," ; 253 } 254perfer_core_id_vec_str .pop_back (); 255GGML_LOG_DEBUG ("SPACEMIT_PERFER_CORE_ID is set, perferred core ids: %s\n" ,perfer_core_id_vec_str .c_str ()); 256num_perfer_cores = static_cast < int > (perfer_core_id_vec .size ()); 257 } 258 259use_ime1 = perfer_core_arch_id == spine_core_arch_id::core_arch_a60 || 260perfer_core_arch_id == spine_core_arch_id::core_arch_x100 ; 261 262use_ime2 = perfer_core_arch_id == spine_core_arch_id::core_arch_a100 ; 263 264mem_backend = parse_mem_backend (getenv ("SPACEMIT_MEM_BACKEND" )); 265char * spine_disable_tcm_str = getenv ("SPACEMIT_DISABLE_TCM" ); 266auto user_disable_tcm = spine_disable_tcm_str != nullptr && strcmp (spine_disable_tcm_str ,"0" )!= 0 ; 267 268if (!user_disable_tcm ) { 269spine_mem_pool_tcm_info tcm_info ; 270if (spine_mem_pool_tcm_init (& tcm_info )) { 271use_tcm = tcm_info .available ; 272tcm_blk_size = tcm_info .blk_size ; 273GGML_LOG_DEBUG ("CPU_RISCV64_SPACEMIT: tcm is available, blk_size: %zu, blk_num: %zu, is_fake_tcm: %d\n" , 274tcm_info .blk_size ,tcm_info .blk_num ,tcm_info .is_fake_tcm ); 275 276for (auto & core_info :core_info_list ) { 277auto core_arch_head = (uint16_t ) (core_info .arch_id ) >>12 ; 278if (core_arch_head != 0xA ) { 279aicpu_id_offset ++ ; 280 }else { 281break ; 282 } 283 } 284 } 285 } 286 287GGML_LOG_DEBUG ( 288"CPU_RISCV64_SPACEMIT: num_cores: %d, num_perfer_cores: %d, perfer_core_arch_id: %x, exclude_main_thread: %d, " 289"use_ime1: %d, use_ime2: %d, mem_backend: %s, cpu_mask: %lx, aicpu_id_offset: %d\n" , 290num_cores ,num_perfer_cores , (uint16_t )perfer_core_arch_id ,exclude_main_thread ,use_ime1 ,use_ime2 , 291spine_mem_pool_backend_to_string (mem_backend ),cpu_mask ,aicpu_id_offset ); 292 293const size_t init_barrier_size = sizeof (spine_barrier_t )* spine_init_barrier_count ; 294init_barrier = 295static_cast < spine_barrier_t *> (spine_mem_pool_shared_mem_alloc (init_barrier_size , alignof(spine_barrier_t ))); 296if (init_barrier != nullptr ) { 297init_barrier_is_shared_mem = true; 298 }else { 299GGML_LOG_WARN ("CPU_RISCV64_SPACEMIT: failed to allocate init_barrier from shared mem, falling back to heap\n" , 300__func__ ); 301init_barrier = new spine_barrier_t [spine_init_barrier_count ]; 302 } 303 304spine_barrier_init (init_barrier ,spine_init_barrier_count ,2 ); 305} 306 307spine_env_info::~spine_env_info () { 308if (init_barrier_is_shared_mem ) { 309spine_mem_pool_shared_mem_free (init_barrier ); 310 }else { 311delete []init_barrier ; 312 } 313 314init_barrier = nullptr ; 315init_barrier_is_shared_mem = false; 316} 317 318spine_env_info global_spine_env_info ; 319 320}// namespace ggml::cpu::riscv64_spacemit