Safetensors
GGUF
Turkish
llama
Llama-3
instruct
finetune
chatml
gpt4
synthetic data
distillation
function calling
json mode
axolotl
roleplaying
chat
Instructions to use tda45/TdAI with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- llama-cpp-python
How to use tda45/TdAI with llama-cpp-python:
# !pip install llama-cpp-python from llama_cpp import Llama llm = Llama.from_pretrained( repo_id="tda45/TdAI", filename="llama.cpp/models/ggml-vocab-aquila.gguf", )
output = llm( "Once upon a time,", max_tokens=512, echo=True ) print(output)
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use tda45/TdAI with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf tda45/TdAI # Run inference directly in the terminal: llama cli -hf tda45/TdAI
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf tda45/TdAI # Run inference directly in the terminal: llama cli -hf tda45/TdAI
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf tda45/TdAI # Run inference directly in the terminal: ./llama-cli -hf tda45/TdAI
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf tda45/TdAI # Run inference directly in the terminal: ./build/bin/llama-cli -hf tda45/TdAI
Use Docker
docker model run hf.co/tda45/TdAI
- LM Studio
- Jan
- Ollama
How to use tda45/TdAI with Ollama:
ollama run hf.co/tda45/TdAI
- Unsloth Studio
How to use tda45/TdAI with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for tda45/TdAI to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for tda45/TdAI to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for tda45/TdAI to start chatting
- Atomic Chat new
- Docker Model Runner
How to use tda45/TdAI with Docker Model Runner:
docker model run hf.co/tda45/TdAI
- Lemonade
How to use tda45/TdAI with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull tda45/TdAI
Run and chat with the model
lemonade run user.TdAI-{{QUANT_TAG}}List all available models
lemonade list
| namespace syclex = sycl::ext::oneapi::experimental; | |
| static int ggml_sycl_fattn_vec_get_nthreads_host(const int cc) { | |
| return 128; | |
| GGML_UNUSED(cc); | |
| } | |
| static constexpr int ggml_sycl_fattn_vec_get_nthreads_device() { | |
| return 128; | |
| } | |
| // Currenlty llvm with the amdgcn target dose not support unrolling loops | |
| // that contain a break that can not be resolved at compile time. | |
| template <int D, | |
| int ncols, | |
| int type_K, | |
| int type_V, | |
| bool use_logit_softcap, | |
| int warp_size> // D == head size | |
| static void flash_attn_ext_vec(const char* __restrict__ Q, | |
| const char* __restrict__ K, | |
| const char* __restrict__ V, | |
| const char* __restrict__ mask, | |
| const char* __restrict__ sinks, | |
| const int* __restrict__ KV_max, | |
| float* __restrict__ dst, | |
| sycl::float2* __restrict__ dst_meta, | |
| const float scale, | |
| const float max_bias, | |
| const float m0, | |
| const float m1, | |
| const uint32_t n_head_log2, | |
| const float logit_softcap, | |
| const int32_t ne00, | |
| const sycl::uint3 ne01, | |
| const int32_t ne02, | |
| const int32_t ne03, | |
| const int32_t nb01, | |
| const int32_t nb02, | |
| const int32_t nb03, | |
| const int32_t ne10, | |
| const int32_t ne11, | |
| const int32_t ne12, | |
| const int32_t ne13, | |
| const int32_t nb11, | |
| const int32_t nb12, | |
| const int64_t nb13, | |
| const int32_t nb21, | |
| const int32_t nb22, | |
| const int64_t nb23, | |
| const int32_t ne31, | |
| const int32_t ne32, | |
| const int32_t ne33, | |
| const int32_t nb31, | |
| const int32_t nb32, | |
| const int64_t nb33) { | |
| // Skip unused kernel variants for faster compilation: | |
| auto item_ct1 = sycl::ext::oneapi::this_work_item::get_nd_item<3>(); | |
| if (use_logit_softcap && !(D == 128 || D == 256)) { | |
| GGML_UNUSED_VARS(Q, K, V, mask, sinks, KV_max, dst, dst_meta, scale, | |
| max_bias, m0, m1, n_head_log2, logit_softcap, | |
| ne00, ne01, ne02, ne03, | |
| nb01, nb02, nb03, | |
| ne10, ne11, ne12, ne13, | |
| nb11, nb12, nb13, | |
| nb21, nb22, nb23, | |
| ne31, ne32, ne33, | |
| nb31, nb32, nb33); | |
| return; | |
| } | |
| //In this kernel Q, K, V are matrices while i, j, k are matrix indices. | |
| constexpr int cpy_nb = ggml_sycl_get_max_cpy_bytes(); | |
| constexpr int cpy_ne = cpy_nb / 4; | |
| constexpr int nthreads_KQ_q = (D/4 < warp_size ? D/4 : warp_size); | |
| constexpr int nthreads_V_q = (D/4 < warp_size ? D/4 : warp_size); | |
| constexpr int nthreads = ggml_sycl_fattn_vec_get_nthreads_device(); | |
| constexpr int nthreads_KQ = type_K == GGML_TYPE_F16 ? 128 / cpy_nb : nthreads_KQ_q; | |
| constexpr int nthreads_V = type_V == GGML_TYPE_F16 ? 128 / cpy_nb : nthreads_V_q; | |
| static_assert(warp_size % nthreads_KQ == 0, "bad nthreads_K"); | |
| static_assert(warp_size % nthreads_V == 0, "bad nthreads_V"); | |
| constexpr int V_rows_per_thread = type_V == GGML_TYPE_F16 ? 2*cpy_ne : 4; | |
| constexpr int V_cols_per_iter = warp_size / nthreads_V; | |
| constexpr vec_dot_KQ_t vec_dot_KQ = get_vec_dot_KQ<type_K, D, nthreads_KQ, warp_size>(); | |
| constexpr bool Q_q8_1 = type_K != GGML_TYPE_F16; | |
| constexpr dequantize_V_t dequantize_V = get_dequantize_V<type_V, sycl::half, V_rows_per_thread>(); | |
| constexpr dequantize_V_t dequantize_V = get_dequantize_V<type_V, float, V_rows_per_thread>(); | |
| const int ic0 = item_ct1.get_group(2) * ncols; // Index of the Q/QKV column to work on. | |
| const int sequence = item_ct1.get_group(0) / ne02; | |
| const int head = item_ct1.get_group(0) - sequence * ne02; | |
| const int gqa_ratio = ne02 / ne12; // With grouped query attention there are > 1 Q matrices per K, V matrix. | |
| Q += nb03*sequence + nb02* head + nb01*ic0; | |
| K += nb13*sequence + nb12*(head / gqa_ratio); | |
| V += nb23*sequence + nb22*(head / gqa_ratio); | |
| const sycl::half * maskh = (const sycl::half *) (mask + nb33 * (sequence % ne33) + nb31 * ic0); | |
| const float slope = get_alibi_slope(max_bias, head, n_head_log2, m0, m1); | |
| static_assert(D % (2*warp_size) == 0, "D not divisible by 2*warp_size == 64."); | |
| constexpr int nwarps = nthreads / warp_size; | |
| const int tid = warp_size * item_ct1.get_local_id(1) + item_ct1.get_local_id(2); | |
| __builtin_assume(tid < nthreads); | |
| constexpr int ne_KQ = ncols*D; | |
| constexpr int ne_combine = nwarps*V_cols_per_iter*D; | |
| constexpr size_t lsm_size1 = ncols * warp_size; | |
| constexpr size_t lsm_size2 = ncols * warp_size; | |
| sycl::half2 VKQ[ncols][(D / 2) / nthreads_V] = { { { 0.0f, 0.0f } } }; | |
| constexpr size_t lsm_size3 = (ne_KQ > ne_combine ? ne_KQ : ne_combine); | |
| constexpr size_t local_share_mem_size = (lsm_size1 + lsm_size2)*sizeof(float) + lsm_size3*sizeof(sycl::half); | |
| syclex::work_group_static<char[local_share_mem_size]> lsm; | |
| float *KQ_max_shared = (float *)&lsm; | |
| float *KQ_sum_shared = KQ_max_shared+lsm_size1; | |
| sycl::half* KQ = (sycl::half*)(KQ_sum_shared + lsm_size2); | |
| sycl::float2 VKQ[ncols][(D/2)/nthreads_V] = {{{0.0f, 0.0f}}}; | |
| constexpr size_t lsm_size3 = (ne_KQ > ne_combine ? ne_KQ : ne_combine); | |
| constexpr size_t local_share_mem_size = (lsm_size1 + lsm_size2 + lsm_size3)*sizeof(float); | |
| syclex::work_group_static<char[local_share_mem_size]> lsm; | |
| float *KQ_max_shared = (float *)&lsm; | |
| float *KQ_sum_shared = KQ_max_shared+lsm_size1; | |
| float* KQ = KQ_sum_shared + lsm_size2; | |
| float KQ_max[ncols]; | |
| float KQ_sum[ncols]; | |
| for (int j = 0; j < ncols; ++j) { | |
| KQ_max[j] = -FLT_MAX/2.0f; | |
| KQ_sum[j] = 0.0f; | |
| } | |
| // Convert Q to float2 (f16 K) or q8_1 (quantized K) and store in registers: | |
| sycl::half2 Q_reg[ncols][(D / 2) / nthreads_KQ] = {{{0.0f, 0.0f}}}; // Will be initialized completely. | |
| sycl::float2 Q_reg[ncols][(D/2)/nthreads_KQ] = {{{0.0f, 0.0f}}}; // May be only partially initialized. | |
| int Q_i32[ncols][1 > D/(sizeof(int)*nthreads_KQ) ? 1 : D/(sizeof(int)*nthreads_KQ)]; | |
| sycl::float2 Q_ds[ncols][1 > D / (sizeof(int) * nthreads_KQ) ? 1 : D / (sizeof(int) * nthreads_KQ)]; | |
| if constexpr (Q_q8_1) { | |
| for (int j0 = 0; j0 < ncols; j0 += nwarps) { | |
| const int j = j0 + item_ct1.get_local_id(1); | |
| if (j0 + nwarps > ncols && j >= ncols) { | |
| break; | |
| } | |
| // Reuse KQ as temporary storage for converting Q to q8_1: | |
| int * tmp_q_i32 = (int *) &KQ[j*D]; | |
| sycl::float2 * tmp_q_ds = (sycl::float2 *) (tmp_q_i32 + D / sizeof(int)); | |
| // Set memory to zero if out of bounds: | |
| if (ncols > 1 && ic0 + j >= int(ne01.z())) { | |
| for (int i0 = 0; i0 < int(D/sizeof(int)); i0 += warp_size) { | |
| const int i = i0 + item_ct1.get_local_id(2); | |
| if (i0 + warp_size <= int(D/sizeof(int)) || i < int(D/sizeof(int))) { | |
| tmp_q_i32[i] = 0; | |
| } | |
| } | |
| if (item_ct1.get_local_id(2) < D/QK8_1) { | |
| tmp_q_ds[item_ct1.get_local_id(2)] = sycl::float2(0.0f, 0.0f); | |
| } | |
| } else { | |
| const float * Q_f = (const float *) (Q + j*nb01); | |
| constexpr int nthreads_quantize = D/sizeof(int) < warp_size ? D/sizeof(int) : warp_size; | |
| for (int i0 = 0; i0 < int(D/sizeof(int)); i0 += nthreads_quantize) { | |
| quantize_q8_1_to_shared<sycl::float2, nthreads_quantize, warp_size> | |
| (Q_f + i0*sizeof(int), scale, tmp_q_i32 + i0, tmp_q_ds + i0/QI8_1); | |
| } | |
| } | |
| } | |
| item_ct1.barrier(sycl::access::fence_space::local_space); | |
| for (int j = 0; j < ncols; ++j) { | |
| int * tmp_q_i32 = (int *) &KQ[j*D]; | |
| sycl::float2 * tmp_q_ds = (sycl::float2 *) (tmp_q_i32 + D / sizeof(int)); | |
| for (int i0 = 0; i0 < int(D/sizeof(int)); i0 += nthreads_KQ) { | |
| const int i = | |
| i0 + (nthreads_KQ == warp_size ? item_ct1.get_local_id(2) : item_ct1.get_local_id(2) % nthreads_KQ); | |
| Q_i32[j][i0/nthreads_KQ] = tmp_q_i32[i]; | |
| Q_ds[j][i0/nthreads_KQ] = tmp_q_ds[i/QI8_1]; | |
| } | |
| } | |
| item_ct1.barrier(sycl::access::fence_space::local_space); | |
| } else { | |
| const sycl::half2 scale_h2 = sycl::half2(scale, scale); | |
| for (int j = 0; j < ncols; ++j) { | |
| const sycl::float2 * Q_j = (const sycl::float2 *) (Q + j * nb01); | |
| for (int i0 = 0; i0 < D/2; i0 += nthreads_KQ*cpy_ne) { | |
| const int i = i0 + (nthreads_KQ == warp_size ? item_ct1.get_local_id(2) : | |
| item_ct1.get_local_id(2) % nthreads_KQ) * | |
| cpy_ne; | |
| sycl::float2 tmp[cpy_ne] = { | |
| { 0.0f, 0.0f } | |
| }; | |
| if (ncols == 1 || ic0 + j < int(ne01.z())) { | |
| ggml_sycl_memcpy_1<cpy_nb>(tmp, &Q_j[i]); | |
| ggml_sycl_memcpy_1<cpy_nb>(tmp + cpy_ne/2, &Q_j[i + cpy_ne/2]); | |
| } | |
| for (int i1 = 0; i1 < cpy_ne; ++i1) { | |
| Q_reg[j][i0 / nthreads_KQ + i1] = sycl::half2(tmp[i1].x(), tmp[i1].y()); | |
| } | |
| } | |
| for (int k = 0; k < (D/2)/nthreads_KQ; ++k) { | |
| Q_reg[j][k] *= scale_h2; | |
| } | |
| } | |
| for (int j = 0; j < ncols; ++j) { | |
| const sycl::float2 * Q_j = (const sycl::float2 *) (Q + j*nb01); | |
| for (int i0 = 0; i0 < D/2; i0 += nthreads_KQ*cpy_ne) { | |
| const int i = i0 + (nthreads_KQ == warp_size ? item_ct1.get_local_id(2) : item_ct1.get_local_id(2) % nthreads_KQ)*cpy_ne; | |
| if (ncols == 1 || ic0 + j < int(ne01.z())) { | |
| ggml_sycl_memcpy_1<cpy_nb>(&Q_reg[j][i0/nthreads_KQ], &Q_j[i]); | |
| ggml_sycl_memcpy_1<cpy_nb>(&Q_reg[j][i0/nthreads_KQ + cpy_ne/2], &Q_j[i + cpy_ne/2]); | |
| } | |
| } | |
| for (int k = 0; k < (D/2)/nthreads_KQ; ++k) { | |
| Q_reg[j][k].x() *= scale; | |
| Q_reg[j][k].y() *= scale; | |
| } | |
| } | |
| } | |
| const int k_VKQ_max = KV_max ? KV_max[sequence * item_ct1.get_group_range(2) + item_ct1.get_group(2)] : ne11; | |
| K += item_ct1.get_group(1) * nthreads * nb11; | |
| V += item_ct1.get_group(1) * nthreads * nb21; | |
| maskh += item_ct1.get_group(1) * nthreads; | |
| for (int k_VKQ_0 = item_ct1.get_group(1) * nthreads; k_VKQ_0 < k_VKQ_max; | |
| k_VKQ_0 += item_ct1.get_group_range(1) * nthreads, | |
| // Increment pointers after each loop: | |
| K += item_ct1.get_group_range(1) * nthreads * nb11, V += item_ct1.get_group_range(1) * nthreads * nb21, | |
| maskh += item_ct1.get_group_range(1) * nthreads) { | |
| // Calculate KQ tile and keep track of new maximum KQ values: | |
| float KQ_reg[ncols]={}; // KQ in registers. | |
| float KQ_max_new[ncols]={}; | |
| for (int j = 0; j < ncols; ++j) { | |
| KQ_max_new[j] = KQ_max[j]; | |
| } | |
| for (int i_KQ_0 = 0; i_KQ_0 < nthreads_KQ; ++i_KQ_0) { | |
| const int i_KQ = item_ct1.get_local_id(1) * warp_size + | |
| (nthreads_KQ == warp_size ? 0 : (item_ct1.get_local_id(2) & ~(nthreads_KQ - 1))) + i_KQ_0; | |
| for (int j = 0; j < ncols; ++j) { | |
| float sum = vec_dot_KQ(K + i_KQ*nb11, Q_reg[j], Q_i32[j], Q_ds[j]); | |
| sum = warp_reduce_sum<nthreads_KQ>(sum); | |
| if (use_logit_softcap) { | |
| sum = logit_softcap * sycl::tanh(sum); | |
| } | |
| if (mask) { | |
| sum += slope * sycl::vec<sycl::half, 1>(maskh[j * ne11 + i_KQ]) | |
| .convert<float, sycl::rounding_mode::automatic>()[0]; | |
| } | |
| KQ_max_new[j] = sycl::fmax((float) KQ_max_new[j], sum); | |
| if (int(nthreads_KQ == warp_size ? item_ct1.get_local_id(2) | |
| : item_ct1.get_local_id(2) % | |
| nthreads_KQ) == i_KQ_0) { | |
| KQ_reg[j] = sum; | |
| } | |
| } | |
| } | |
| for (int j = 0; j < ncols; ++j) { | |
| for (int offset = nthreads_KQ; offset < warp_size; offset <<= 1) { | |
| KQ_max_new[j] = sycl::fmax( | |
| (float)KQ_max_new[j], | |
| (float)dpct::permute_sub_group_by_xor( | |
| sycl::ext::oneapi::this_work_item::get_sub_group(), | |
| KQ_max_new[j], | |
| offset, | |
| warp_size)); | |
| } | |
| const float KQ_max_scale = sycl::native::exp((float) (KQ_max[j] - KQ_max_new[j])); | |
| KQ_max[j] = KQ_max_new[j]; | |
| KQ_reg[j] = sycl::native::exp((float) (KQ_reg[j] - KQ_max[j])); | |
| KQ_sum[j] = KQ_sum[j]*KQ_max_scale + KQ_reg[j]; | |
| KQ[j*nthreads + tid] = KQ_reg[j]; | |
| const sycl::half2 KQ_max_scale_h2 = sycl::half2(KQ_max_scale, KQ_max_scale); | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V) { | |
| VKQ[j][i_VKQ_0/nthreads_V] *= KQ_max_scale_h2; | |
| } | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V) { | |
| VKQ[j][i_VKQ_0/nthreads_V].x() *= KQ_max_scale; | |
| VKQ[j][i_VKQ_0/nthreads_V].y() *= KQ_max_scale; | |
| } | |
| } | |
| sycl::group_barrier(sycl::ext::oneapi::this_work_item::get_sub_group()); | |
| for (int k0 = 0; k0 < warp_size; k0 += V_cols_per_iter) { | |
| const int k = item_ct1.get_local_id(1) * warp_size + k0 + | |
| (nthreads_V == warp_size ? 0 : item_ct1.get_local_id(2) / nthreads_V); | |
| sycl::half2 KQ_k[ncols]; | |
| for (int j = 0; j < ncols; ++j) { | |
| KQ_k[j] = sycl::half2(KQ[j * nthreads + k]); | |
| } | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V*V_rows_per_thread/2) { | |
| sycl::half2 tmp[V_rows_per_thread / 2]; | |
| dequantize_V(V + k * nb21, tmp, | |
| 2 * i_VKQ_0 + (nthreads_V == warp_size ? item_ct1.get_local_id(2) : | |
| item_ct1.get_local_id(2) % nthreads_V) * | |
| V_rows_per_thread); | |
| for (int i_VKQ_1 = 0; i_VKQ_1 < V_rows_per_thread/2; ++i_VKQ_1) { | |
| for (int j = 0; j < ncols; ++j) { | |
| VKQ[j][i_VKQ_0/nthreads_V + i_VKQ_1] += tmp[i_VKQ_1]*KQ_k[j]; | |
| } | |
| } | |
| } | |
| float KQ_k[ncols]; | |
| for (int j = 0; j < ncols; ++j) { | |
| KQ_k[j] = KQ[j*nthreads + k]; | |
| } | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V*V_rows_per_thread/2) { | |
| sycl::float2 tmp[V_rows_per_thread/2]; | |
| dequantize_V(V + k*nb21, tmp, | |
| 2*i_VKQ_0 + (nthreads_V == warp_size ? item_ct1.get_local_id(2) : item_ct1.get_local_id(2) % nthreads_V)*V_rows_per_thread); | |
| for (int i_VKQ_1 = 0; i_VKQ_1 < V_rows_per_thread/2; ++i_VKQ_1) { | |
| for (int j = 0; j < ncols; ++j) { | |
| VKQ[j][i_VKQ_0/nthreads_V + i_VKQ_1].x() += tmp[i_VKQ_1].x()*KQ_k[j]; | |
| VKQ[j][i_VKQ_0/nthreads_V + i_VKQ_1].y() += tmp[i_VKQ_1].y()*KQ_k[j]; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (sinks && item_ct1.get_group(1) == 0) { | |
| const float sink = ((const float *) sinks)[head]; | |
| for (int j0 = 0; j0 < ncols; j0 += nwarps) { | |
| const int j = j0 + item_ct1.get_local_id(1); | |
| if (j0 + nwarps > ncols && j >= ncols) { | |
| break; | |
| } | |
| const float kqmax_new_j = sycl::fmax(sink, (float) KQ_max[j]); | |
| const float KQ_max_scale = sycl::native::exp((float) (KQ_max[j] - kqmax_new_j)); | |
| KQ_max[j] = kqmax_new_j; | |
| KQ_sum[j] = KQ_sum[j] * KQ_max_scale + | |
| (item_ct1.get_local_id(2) == 0 ? sycl::native::exp((float) (sink - KQ_max[j])) : 0.0f); | |
| const sycl::half2 KQ_max_scale_h2 = sycl::half2(KQ_max_scale, KQ_max_scale); | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V) { | |
| VKQ[j][i_VKQ_0/nthreads_V] *= KQ_max_scale_h2; | |
| } | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V) { | |
| VKQ[j][i_VKQ_0/nthreads_V].x() *= KQ_max_scale; | |
| VKQ[j][i_VKQ_0/nthreads_V].y() *= KQ_max_scale; | |
| } | |
| } | |
| } | |
| for (int j = 0; j < ncols; ++j) { | |
| if (item_ct1.get_local_id(1) == 0) { | |
| KQ_max_shared[j*warp_size+item_ct1.get_local_id(2)] = -FLT_MAX / 2.0f; | |
| KQ_sum_shared[j*warp_size+item_ct1.get_local_id(2)] = 0.0f; | |
| } | |
| } | |
| item_ct1.barrier(sycl::access::fence_space::local_space); | |
| for (int j = 0; j < ncols; ++j) { | |
| if (item_ct1.get_local_id(2) == 0) { | |
| KQ_max_shared[j*warp_size+item_ct1.get_local_id(1)] = KQ_max[j]; | |
| } | |
| } | |
| item_ct1.barrier(sycl::access::fence_space::local_space); | |
| for (int j_VKQ = 0; j_VKQ < ncols; ++j_VKQ) { | |
| if (ncols > 1 && ic0 + j_VKQ >= int(ne01.z())) { | |
| break; | |
| } | |
| float kqmax_new = KQ_max_shared[j_VKQ*warp_size+item_ct1.get_local_id(2)]; | |
| kqmax_new = warp_reduce_max<warp_size>(kqmax_new); | |
| const float kqmax_scale = sycl::native::exp((float) (KQ_max[j_VKQ] - kqmax_new)); | |
| KQ_max[j_VKQ] = kqmax_new; | |
| sycl::half2 * VKQ_tmp = (sycl::half2 *) KQ + item_ct1.get_local_id(1) * (V_cols_per_iter * D / 2) + | |
| (nthreads_V == warp_size ? 0 : item_ct1.get_local_id(2) / nthreads_V) * (D / 2); | |
| const sycl::half2 kqmax_scale_h2 = sycl::half2(kqmax_scale, kqmax_scale); | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V) { | |
| VKQ[j_VKQ][i_VKQ_0/nthreads_V] *= kqmax_scale_h2; | |
| } | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V*V_rows_per_thread/2) { | |
| const int i_VKQ = | |
| i_VKQ_0 + (nthreads_V == warp_size ? item_ct1.get_local_id(2) : item_ct1.get_local_id(2) % nthreads_V) * | |
| (V_rows_per_thread / 2); | |
| ggml_sycl_memcpy_1<V_rows_per_thread * sizeof(sycl::half)>(VKQ_tmp + i_VKQ, | |
| &VKQ[j_VKQ][i_VKQ_0 / nthreads_V]); | |
| } | |
| sycl::float2 * VKQ_tmp = (sycl::float2 *) KQ + item_ct1.get_local_id(1)*(V_cols_per_iter*D/2) | |
| + (nthreads_V == warp_size ? 0 : item_ct1.get_local_id(2) / nthreads_V)*(D/2); | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V) { | |
| VKQ[j_VKQ][i_VKQ_0/nthreads_V].x() *= kqmax_scale; | |
| VKQ[j_VKQ][i_VKQ_0/nthreads_V].y() *= kqmax_scale; | |
| } | |
| for (int i_VKQ_0 = 0; i_VKQ_0 < D/2; i_VKQ_0 += nthreads_V*V_rows_per_thread/2) { | |
| const int i_VKQ = i_VKQ_0 + (nthreads_V == warp_size ? item_ct1.get_local_id(2) : item_ct1.get_local_id(2) % nthreads_V)*(V_rows_per_thread/2); | |
| ggml_sycl_memcpy_1<V_rows_per_thread/2*sizeof(float)>(VKQ_tmp + i_VKQ, &VKQ[j_VKQ][i_VKQ_0/nthreads_V]); | |
| ggml_sycl_memcpy_1<V_rows_per_thread/2*sizeof(float)>(VKQ_tmp + i_VKQ + V_rows_per_thread/4, &VKQ[j_VKQ][i_VKQ_0/nthreads_V + V_rows_per_thread/4]); | |
| } | |
| KQ_sum[j_VKQ] *= kqmax_scale; | |
| KQ_sum[j_VKQ] = warp_reduce_sum<warp_size>(KQ_sum[j_VKQ]); | |
| if (item_ct1.get_local_id(2) == 0) { | |
| KQ_sum_shared[j_VKQ*warp_size+item_ct1.get_local_id(1)] = KQ_sum[j_VKQ]; | |
| } | |
| item_ct1.barrier(sycl::access::fence_space::local_space); | |
| if (nthreads <= D || tid < D) { | |
| KQ_sum[j_VKQ] = KQ_sum_shared[j_VKQ*warp_size+item_ct1.get_local_id(2)]; | |
| KQ_sum[j_VKQ] = warp_reduce_sum<warp_size>(KQ_sum[j_VKQ]); | |
| for (int i0 = 0; i0 < D; i0 += nthreads) { | |
| float dst_val = 0; | |
| for (int w = 0; w < nwarps; ++w) { | |
| for (int v = 0; v < V_cols_per_iter; ++v) { | |
| dst_val += float(KQ[w*V_cols_per_iter*D + v*D + i0 + tid]); | |
| } | |
| } | |
| if (item_ct1.get_group_range(1) == 1) { | |
| dst_val /= KQ_sum[j_VKQ]; | |
| } | |
| dst[(((sequence * int(ne01.z()) + ic0 + j_VKQ) * ne02 + head) * item_ct1.get_group_range(1) + | |
| item_ct1.get_group(1)) * | |
| D + | |
| i0 + tid] = dst_val; | |
| } | |
| } | |
| if (j_VKQ < ncols-1) { | |
| item_ct1.barrier(sycl::access::fence_space::local_space); | |
| } | |
| } | |
| if (item_ct1.get_group_range(1) != 1 && tid < ncols && (ncols == 1 || ic0 + tid < int(ne01.z()))) { | |
| dst_meta[((sequence * int(ne01.z()) + ic0 + tid) * ne02 + head) * item_ct1.get_group_range(1) + | |
| item_ct1.get_group(1)] = make_float2(KQ_max[tid], KQ_sum[tid]); | |
| } | |
| GGML_UNUSED_VARS(Q, K, V, mask, sinks, KV_max, dst, dst_meta, scale, | |
| max_bias, m0, m1, n_head_log2, logit_softcap, | |
| ne00, ne01, ne02, ne03, | |
| nb01, nb02, nb03, | |
| ne10, ne11, ne12, ne13, | |
| nb11, nb12, nb13, | |
| nb21, nb22, nb23, | |
| ne31, ne32, ne33, | |
| nb31, nb32, nb33); | |
| } | |
| template <int D, int cols_per_block, int type_K, int type_V, bool use_logit_softcap> | |
| void ggml_sycl_flash_attn_ext_vec_case_impl(ggml_backend_sycl_context & ctx, ggml_tensor * dst) { | |
| const int warp_size = WARP_16_SIZE; //better performance than WARP_32_SIZE | |
| const int cc = ggml_sycl_info().devices[ggml_sycl_get_device()].cc; | |
| const int nthreads = ggml_sycl_fattn_vec_get_nthreads_host(cc); | |
| const int nwarps = nthreads / warp_size; | |
| const bool need_f16_K = type_K == GGML_TYPE_F16; | |
| const bool need_f16_V = type_V == GGML_TYPE_F16; | |
| constexpr size_t nbytes_shared = 0; | |
| launch_fattn<D, cols_per_block, 1, | |
| flash_attn_ext_vec<D, cols_per_block, type_K, type_V, | |
| use_logit_softcap, warp_size>, warp_size>( | |
| ctx, dst, nwarps, nbytes_shared, D, need_f16_K, need_f16_V, false); | |
| } | |
| template <int D, int type_K, int type_V> | |
| void ggml_sycl_flash_attn_ext_vec_case(ggml_backend_sycl_context & ctx, ggml_tensor * dst) { | |
| const ggml_tensor * KQV = dst; | |
| const ggml_tensor * Q = dst->src[0]; | |
| float logit_softcap; | |
| memcpy(&logit_softcap, (const float *) KQV->op_params + 2, sizeof(float)); | |
| if (Q->ne[1] == 1) { | |
| constexpr int cols_per_block = 1; | |
| if (logit_softcap == 0.0f) { | |
| constexpr bool use_logit_softcap = false; | |
| ggml_sycl_flash_attn_ext_vec_case_impl<D, cols_per_block, type_K, type_V, use_logit_softcap>(ctx, dst); | |
| } else { | |
| constexpr bool use_logit_softcap = true; | |
| ggml_sycl_flash_attn_ext_vec_case_impl<D, cols_per_block, type_K, type_V, use_logit_softcap>(ctx, dst); | |
| } | |
| return; | |
| } | |
| constexpr int cols_per_block = 2; | |
| if (logit_softcap == 0.0f) { | |
| constexpr bool use_logit_softcap = false; | |
| ggml_sycl_flash_attn_ext_vec_case_impl<D, cols_per_block, type_K, type_V, use_logit_softcap>(ctx, dst); | |
| } else { | |
| constexpr bool use_logit_softcap = true; | |
| ggml_sycl_flash_attn_ext_vec_case_impl<D, cols_per_block, type_K, type_V, use_logit_softcap>(ctx, dst); | |
| } | |
| } | |
| EXTERN_DECL_FATTN_VEC_CASES( 64, GGML_TYPE_F16) | |
| EXTERN_DECL_FATTN_VEC_CASES( 64, GGML_TYPE_Q4_0) | |
| EXTERN_DECL_FATTN_VEC_CASES( 64, GGML_TYPE_Q4_1) | |
| EXTERN_DECL_FATTN_VEC_CASES( 64, GGML_TYPE_Q5_0) | |
| EXTERN_DECL_FATTN_VEC_CASES( 64, GGML_TYPE_Q5_1) | |
| EXTERN_DECL_FATTN_VEC_CASES( 64, GGML_TYPE_Q8_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(128, GGML_TYPE_F16) | |
| EXTERN_DECL_FATTN_VEC_CASES(128, GGML_TYPE_Q4_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(128, GGML_TYPE_Q4_1) | |
| EXTERN_DECL_FATTN_VEC_CASES(128, GGML_TYPE_Q5_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(128, GGML_TYPE_Q5_1) | |
| EXTERN_DECL_FATTN_VEC_CASES(128, GGML_TYPE_Q8_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(256, GGML_TYPE_F16) | |
| EXTERN_DECL_FATTN_VEC_CASES(256, GGML_TYPE_Q4_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(256, GGML_TYPE_Q4_1) | |
| EXTERN_DECL_FATTN_VEC_CASES(256, GGML_TYPE_Q5_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(256, GGML_TYPE_Q5_1) | |
| EXTERN_DECL_FATTN_VEC_CASES(256, GGML_TYPE_Q8_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(512, GGML_TYPE_F16) | |
| EXTERN_DECL_FATTN_VEC_CASES(512, GGML_TYPE_Q4_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(512, GGML_TYPE_Q4_1) | |
| EXTERN_DECL_FATTN_VEC_CASES(512, GGML_TYPE_Q5_0) | |
| EXTERN_DECL_FATTN_VEC_CASES(512, GGML_TYPE_Q5_1) | |
| EXTERN_DECL_FATTN_VEC_CASES(512, GGML_TYPE_Q8_0) | |