char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
d6f303004
char/aliceai-t5-moe
1#include "amx.h" 2#include "common.h" 3#include "mmq.h" 4#include "ggml-backend-impl.h" 5#include "ggml-backend.h" 6#include "ggml-impl.h" 7#include "ggml-cpu.h" 8#include "traits.h" 9 10#if defined(__linux__ ) 11#include <sys/syscall.h> 12#include <unistd.h> 13#endif 14 15#include <cstdlib> 16#include <cstring> 17#include <memory> 18 19#if defined(__AMX_INT8__ )&& defined(__AVX512VNNI__ ) 20 21// AMX type_trais 22namespace ggml::cpu::amx { 23class tensor_traits :public ggml::cpu::tensor_traits { 24bool work_size (int /* n_threads */ ,const struct ggml_tensor * op ,size_t & size )override { 25size = ggml_backend_amx_desired_wsize (op ); 26return true; 27 } 28 29bool compute_forward (struct ggml_compute_params * params ,struct ggml_tensor * op )override { 30if (op -> op == GGML_OP_MUL_MAT ) { 31ggml_backend_amx_mul_mat (params ,op ); 32return true; 33 } 34return false; 35 } 36}; 37 38static ggml::cpu::tensor_traits * get_tensor_traits (ggml_backend_buffer_t ,struct ggml_tensor * ) { 39static tensor_traits traits ; 40return & traits ; 41} 42}// namespace ggml::cpu::amx 43 44// AMX buffer interface 45static void ggml_backend_amx_buffer_free_buffer (ggml_backend_buffer_t buffer ) { 46free (buffer -> context ); 47} 48 49static void * ggml_backend_amx_buffer_get_base (ggml_backend_buffer_t buffer ) { 50return (void * ) (buffer -> context ); 51} 52 53static enum ggml_status ggml_backend_amx_buffer_init_tensor (ggml_backend_buffer_t buffer ,struct ggml_tensor * tensor ) { 54tensor -> extra = (void * ) ggml::cpu::amx::get_tensor_traits (buffer ,tensor ); 55 56GGML_UNUSED (buffer ); 57return GGML_STATUS_SUCCESS ; 58} 59 60static void ggml_backend_amx_buffer_memset_tensor (ggml_backend_buffer_t buffer ,struct ggml_tensor * tensor , 61uint8_t value ,size_t offset ,size_t size ) { 62memset ((char * )tensor -> data + offset ,value ,size ); 63 64GGML_UNUSED (buffer ); 65} 66 67static void ggml_backend_amx_buffer_set_tensor (ggml_backend_buffer_t buffer ,struct ggml_tensor * tensor , 68const void * data ,size_t offset ,size_t size ) { 69if (qtype_has_amx_kernels (tensor -> type )) { 70GGML_LOG_DEBUG ("%s: amx repack tensor %s of type %s\n" ,__func__ ,tensor -> name ,ggml_type_name (tensor -> type )); 71ggml_backend_amx_convert_weight (tensor ,data ,offset ,size ); 72 }else { 73memcpy ((char * )tensor -> data + offset ,data ,size ); 74 } 75 76GGML_UNUSED (buffer ); 77} 78 79/* 80// need to figure what we need to do with buffer->extra. 81static void ggml_backend_amx_buffer_get_tensor(ggml_backend_buffer_t buffer, const struct ggml_tensor * tensor, void * data, size_t offset, size_t size) { 82GGML_ASSERT(!qtype_has_amx_kernels(tensor->type)); 83memcpy(data, (const char *)tensor->data + offset, size); 84 85GGML_UNUSED(buffer); 86} 87 88static bool ggml_backend_amx_buffer_cpy_tensor(ggml_backend_buffer_t buffer, const struct ggml_tensor * src, struct ggml_tensor * dst) { 89if (ggml_backend_buffer_is_host(src->buffer)) { 90if (qtype_has_amx_kernels(src->type)) { 91ggml_backend_amx_convert_weight(dst, src->data, 0, ggml_nbytes(dst)); 92} else { 93memcpy(dst->data, src->data, ggml_nbytes(src)); 94} 95return true; 96} 97return false; 98 99GGML_UNUSED(buffer); 100} 101*/ 102 103static void ggml_backend_amx_buffer_clear (ggml_backend_buffer_t buffer ,uint8_t value ) { 104memset (buffer -> context ,value ,buffer -> size ); 105} 106 107static ggml_backend_buffer_i ggml_backend_amx_buffer_interface = { 108/* .free_buffer = */ ggml_backend_amx_buffer_free_buffer , 109/* .get_base = */ ggml_backend_amx_buffer_get_base , 110/* .init_tensor = */ ggml_backend_amx_buffer_init_tensor , 111/* .memset_tensor = */ ggml_backend_amx_buffer_memset_tensor , 112/* .set_tensor = */ ggml_backend_amx_buffer_set_tensor , 113/* .get_tensor = */ nullptr , 114/* .set_tensor_2d = */ nullptr , 115/* .get_tensor_2d = */ nullptr , 116/* .cpy_tensor = */ nullptr , 117/* .clear = */ ggml_backend_amx_buffer_clear , 118/* .reset = */ nullptr , 119}; 120 121static const char * ggml_backend_amx_buffer_type_get_name (ggml_backend_buffer_type_t buft ) { 122return "AMX" ; 123 124GGML_UNUSED (buft ); 125} 126 127static ggml_backend_buffer_t ggml_backend_amx_buffer_type_alloc_buffer (ggml_backend_buffer_type_t buft ,size_t size ) { 128void * data = ggml_aligned_malloc (size ); 129if (data == NULL ) { 130fprintf (stderr ,"%s: failed to allocate buffer of size %zu\n" ,__func__ ,size ); 131return NULL ; 132 } 133 134return ggml_backend_buffer_init (buft ,ggml_backend_amx_buffer_interface ,data ,size ); 135} 136 137static size_t ggml_backend_amx_buffer_type_get_alignment (ggml_backend_buffer_type_t buft ) { 138return TENSOR_ALIGNMENT ; 139 140GGML_UNUSED (buft ); 141} 142 143namespace ggml::cpu::amx { 144class extra_buffer_type : ggml::cpu::extra_buffer_type { 145bool supports_op (ggml_backend_dev_t ,const struct ggml_tensor * op )override { 146if (op -> op != GGML_OP_MUL_MAT ) { 147return false; 148 } 149auto * src0 = op -> src [0 ]; 150auto * src1 = op -> src [1 ]; 151 152if (!ggml_is_contiguous (src0 )|| !ggml_is_contiguous (src1 )) { 153return false; 154 } 155if (!src0 -> buffer || src0 -> buffer -> buft != ggml_backend_amx_buffer_type ()) { 156return false; 157 } 158if (src1 -> buffer && !ggml_backend_buft_is_host (src1 -> buffer -> buft )) { 159return false; 160 } 161if (op -> ne [0 ] % (TILE_N * 2 )) { 162return false; 163 } 164int alignment ; 165switch (src0 -> type ) { 166case GGML_TYPE_Q4_0 : 167case GGML_TYPE_Q4_1 : 168case GGML_TYPE_Q8_0 : 169alignment = TILE_K ; 170break ; 171case GGML_TYPE_Q4_K : 172case GGML_TYPE_Q5_K : 173case GGML_TYPE_Q6_K : 174case GGML_TYPE_IQ4_XS : 175alignment = 256 ;// QK_K 176break ; 177case GGML_TYPE_F16 : 178alignment = 16 ; 179break ; 180default : 181return false; 182 } 183if (src0 -> ne [0 ] %alignment ) { 184return false; 185 } 186if (src1 -> type != GGML_TYPE_F32 ) { 187return false; 188 } 189return true; 190 } 191 192 ggml::cpu::tensor_traits * get_tensor_traits (const struct ggml_tensor * op )override { 193if (op -> op == GGML_OP_MUL_MAT && op -> src [0 ]-> buffer && 194op -> src [0 ]-> buffer -> buft == ggml_backend_amx_buffer_type ()) { 195return (ggml::cpu::tensor_traits * )op -> src [0 ]-> extra ; 196 } 197 198return nullptr ; 199 } 200}; 201}// namespace ggml::cpu::amx 202 203static size_t ggml_backend_amx_buffer_type_get_alloc_size (ggml_backend_buffer_type_t buft ,const ggml_tensor * tensor ) { 204return ggml_backend_amx_get_alloc_size (tensor ); 205 206GGML_UNUSED (buft ); 207} 208 209#define ARCH_GET_XCOMP_PERM 0x1022 210#define ARCH_REQ_XCOMP_PERM 0x1023 211#define XFEATURE_XTILECFG 17 212#define XFEATURE_XTILEDATA 18 213 214static bool ggml_amx_init () { 215#if defined(__linux__ ) 216if (syscall (SYS_arch_prctl ,ARCH_REQ_XCOMP_PERM ,XFEATURE_XTILEDATA )) { 217fprintf (stderr ,"AMX is not ready to be used!\n" ); 218return false; 219 } 220return true; 221#elif defined(_WIN32 ) 222return true; 223#else 224return false; 225#endif 226} 227 228ggml_backend_buffer_type_t ggml_backend_amx_buffer_type () { 229static struct ggml_backend_buffer_type ggml_backend_buffer_type_amx = { 230/* .iface = */ { 231/* .get_name = */ ggml_backend_amx_buffer_type_get_name , 232/* .alloc_buffer = */ ggml_backend_amx_buffer_type_alloc_buffer , 233/* .get_alignment = */ ggml_backend_amx_buffer_type_get_alignment , 234/* .get_max_size = */ nullptr ,// defaults to SIZE_MAX 235/* .get_alloc_size = */ ggml_backend_amx_buffer_type_get_alloc_size , 236/* .is_host = */ nullptr , 237 }, 238/* .device = */ ggml_backend_reg_dev_get (ggml_backend_cpu_reg (),0 ), 239/* .context = */ new ggml::cpu::amx::extra_buffer_type (), 240 }; 241 242if (!ggml_amx_init ()) { 243return nullptr ; 244 } 245 246return & ggml_backend_buffer_type_amx ; 247} 248 249#endif // defined(__AMX_INT8__) && defined(__AVX512VNNI__)