ember.cpp 0.1.0
C++ inference engine for Llama-family and paperkiln models (CPU, CUDA, WebAssembly)
Loading...
Searching...
No Matches
cpu_attention.h
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4#include <cmath>
5#include "kv_cache.h"
6
7// softcap c > 0 (keramos IR_SPEC 5.15 softcap, revision 1.5; Gemma 2): every kernel below caps its scaled score s as
8// c * tanh(s / c), the division rounded, then tanhf, then the product, before any position bias; 0 leaves s.
9inline float softcap_score(float s, float c) { return c > 0.0f ? c * std::tanh(s / c) : s; }
10
11
14 int layer_idx,
15 const std::vector<float>& k_batch_for_layer,
16 const std::vector<float>& v_batch_for_layer,
19 int num_kv_heads,
20 int head_dim
21);
22
24 const std::vector<float>& q_batch_roped,
26 std::vector<float>& batch_attn_output,
29 int num_q_heads,
30 int num_kv_heads,
31 int head_dim,
32 float attention_scale,
33 float softcap = 0.0f
34);
35
36// Sliding-window attention with attention sinks, paperkiln's swa_attention
37// (microtorch/src/ops.cpp): query at absolute position p sees keys
38// [0, sink_hi) and [win_lo, p], with win_lo = max(0, p + 1 - window) and
39// sink_hi = min(sinks, p + 1, win_lo). The window is the last `window`
40// positions including p; sinks are the first `sinks` positions, not counted
41// in the window, and a sink inside the window is seen once. window 0 means
42// unbounded (sinks then have no effect): it calls attention_batch_cpu.
43void swa_visible_ranges(int pos, int window, int sinks, int& sink_hi, int& win_lo);
44
46 const std::vector<float>& q_batch_roped,
48 std::vector<float>& batch_attn_output,
51 int num_q_heads,
52 int num_kv_heads,
53 int head_dim,
54 float attention_scale,
55 int window,
56 int sinks,
57 float softcap = 0.0f
58);
59
60// Attention over an explicit list of visible kv rows per query: token t of
61// the batch sees rows[t] (ascending), each scored, softmaxed (maximum and sum
62// over the listed rows only, in list order) and accumulated exactly as
63// attention_window_batch_cpu does, so a list holding rows 0 .. pos performs
64// attention_batch_cpu's operations in its order. Used by the IR's
65// turn_state mask (graph_ir.cpp), whose rows may be a compact cache.
67 const std::vector<float>& q_batch_roped,
69 std::vector<float>& batch_attn_output,
71 const std::vector<std::vector<int>>& rows,
72 int num_q_heads,
73 int num_kv_heads,
74 int head_dim,
75 float attention_scale,
76 float softcap = 0.0f
77);
78
79// The visible kv rows of each query of a batch at positions start_pos .. start_pos + T - 1 over a cache whose row r
80// holds position r: [0, sink_hi) then [win_lo, p] (swa_visible_ranges), or 0 .. p when window is 0.
81std::vector<std::vector<int>> attention_visible_rows(int num_tokens_in_batch, int start_pos_in_sequence, int window,
82 int sinks);
83// attention_rows_batch_cpu with T5's relative position bias (paperkiln IR_SPEC 5.15 position_bias, revision 1.3):
84// each score is (q . k) * scale, rounded, then + bias[b(p - j) * num_q_heads + h], rounded, with p the query's
85// position (query_pos[t]), j the key's (key_pos[row], or the row itself when key_pos is null) and
86// b(n) = buckets[min(n, buckets.size() - 1)]; bias is the table [B][num_q_heads] row-major. Under grouped-query
87// attention the query head's column. Softmax and accumulation as attention_rows_batch_cpu.
89 const std::vector<float>& q_batch_roped,
91 std::vector<float>& batch_attn_output,
93 const std::vector<std::vector<int>>& rows,
94 const std::vector<int>* key_pos,
95 const std::vector<int>& query_pos,
96 int num_q_heads,
97 int num_kv_heads,
98 int head_dim,
99 float attention_scale,
100 const float* bias,
101 const std::vector<int>& buckets,
102 float softcap = 0.0f
103);
104// attention_rows_batch_cpu with Shaw's relative key and value vectors (keramos IR_SPEC 5.15 relative_kv, revision
105// 1.4; Shaw, Uszkoreit and Vaswani 2018 eqs. 3-4). With p the query's position (query_pos[t]), j the key's
106// (key_pos[row], or the row itself when key_pos is null) and n = min(p - j, max_distance), head h computes
107// s(p, j) = ((q . k_j) + (q . rk[n])) * scale
108// out_p = (sum over the visible j of a v_j) + (sum over the visible j of a rv[n])
109// in the stated order: each dot product sums the head's columns from 0 in ascending order, rounded, then the sum,
110// then the product; each output sum runs from 0 over the visible keys in ascending row order; then the two sums
111// are added. rk (and rv, null for keys only) is the table [max_distance + 1][width] row-major, row n the vectors of
112// distance n; width head_dim (shared by the heads) or num_q_heads * head_dim (head h's at columns h * head_dim).
113// Under grouped-query attention rk[n] and rv[n] are the query head's, k_j and v_j its kv head's. Softmax as
114// attention_rows_batch_cpu.
116 const std::vector<float>& q_batch_roped,
118 std::vector<float>& batch_attn_output,
120 const std::vector<std::vector<int>>& rows,
121 const std::vector<int>* key_pos,
122 const std::vector<int>& query_pos,
123 int num_q_heads,
124 int num_kv_heads,
125 int head_dim,
126 float attention_scale,
127 const float* rk,
128 int rk_width,
129 const float* rv,
130 int rv_width,
131 int max_distance,
132 float softcap = 0.0f
133);
136 int layer_idx,
137 const std::vector<float>& k_batch_for_layer,
138 const std::vector<float>& v_batch_for_layer,
140 const std::vector<int>& sequence_indices,
141 const std::vector<int>& position_in_sequence,
142 int num_kv_heads,
143 int head_dim
144);
145
147 const std::vector<float>& q_batch_roped,
149 std::vector<float>& batch_attn_output,
151 const std::vector<int>& sequence_indices,
152 const std::vector<int>& position_in_sequence,
153 int num_q_heads,
154 int num_kv_heads,
155 int head_dim,
156 float attention_scale,
158);
void attention_batch_cpu_sequence_aware(const std::vector< float > &q_batch_roped, KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< int > &sequence_indices, const std::vector< int > &position_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, int max_seq_len_per_sequence)
std::vector< std::vector< int > > attention_visible_rows(int num_tokens_in_batch, int start_pos_in_sequence, int window, int sinks)
void attention_bias_batch_cpu(const std::vector< float > &q_batch_roped, const KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< std::vector< int > > &rows, const std::vector< int > *key_pos, const std::vector< int > &query_pos, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, const float *bias, const std::vector< int > &buckets, float softcap=0.0f)
void attention_window_batch_cpu(const std::vector< float > &q_batch_roped, KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, int start_pos_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, int window, int sinks, float softcap=0.0f)
void update_kv_cache_batch_cpu_sequence_aware(KVCache *kv_cache, int layer_idx, const std::vector< float > &k_batch_for_layer, const std::vector< float > &v_batch_for_layer, int num_tokens_in_batch, const std::vector< int > &sequence_indices, const std::vector< int > &position_in_sequence, int num_kv_heads, int head_dim)
void attention_relkv_batch_cpu(const std::vector< float > &q_batch_roped, const KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< std::vector< int > > &rows, const std::vector< int > *key_pos, const std::vector< int > &query_pos, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, const float *rk, int rk_width, const float *rv, int rv_width, int max_distance, float softcap=0.0f)
void update_kv_cache_batch_cpu(KVCache *kv_cache, int layer_idx, const std::vector< float > &k_batch_for_layer, const std::vector< float > &v_batch_for_layer, int num_tokens_in_batch, int start_pos_in_sequence, int num_kv_heads, int head_dim)
void swa_visible_ranges(int pos, int window, int sinks, int &sink_hi, int &win_lo)
void attention_batch_cpu(const std::vector< float > &q_batch_roped, KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, int start_pos_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, float softcap=0.0f)
float softcap_score(float s, float c)
void attention_rows_batch_cpu(const std::vector< float > &q_batch_roped, const KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< std::vector< int > > &rows, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, float softcap=0.0f)
float c
size_t j
Key-Value cache for a single transformer layer.
Definition model.h:136
Complete Key-Value cache for all transformer layers.
Definition model.h:157