31 const float *query,
size_t query_elements,
32 const float *key,
size_t key_elements,
33 const float *value,
size_t value_elements,
34 float *output,
size_t output_elements,
35 float *scratch,
size_t scratch_bytes,
36 size_t tokens,
size_t heads,
size_t head_dim)
38 size_t width, elements;
39 if (!query || !key || !value || !output || !scratch ||
41 query_elements < elements || key_elements < elements ||
42 value_elements < elements || output_elements < elements ||
43 tokens > scratch_bytes /
sizeof(
float))
47 for (
size_t i = 0; i < elements; ++i)
48 if (!isfinite(query[i]) || !isfinite(key[i]) || !isfinite(value[i]))
51 const double scale = 1.0 / sqrt((
double)head_dim);
52 for (
size_t t = 0; t < tokens; ++t)
53 for (
size_t h = 0; h < heads; ++h)
54 for (
size_t k = 0; k < tokens; ++k) {
55 const double s =
score(query + t * width + h * head_dim,
56 key + k * width + h * head_dim,
58 if (!isfinite(s) || fabs(s) > FLT_MAX)
62 for (
size_t t = 0; t < tokens; ++t) {
63 for (
size_t h = 0; h < heads; ++h) {
64 const float *q = query + t * width + h * head_dim;
65 double maximum = -INFINITY;
66 for (
size_t k = 0; k < tokens; ++k) {
67 const float *kv = key + k * width + h * head_dim;
68 const double s =
score(q, kv, head_dim, scale);
69 scratch[k] = (float)s;
74 if ((
double)scratch[k] > maximum) maximum = scratch[k];
76 double denominator = 0.0;
77 for (
size_t k = 0; k < tokens; ++k) {
78 scratch[k] = (float)exp((
double)scratch[k] - maximum);
79 denominator += scratch[k];
81 for (
size_t d = 0; d < head_dim; ++d) {
82 double weighted = 0.0;
83 for (
size_t k = 0; k < tokens; ++k) {
84 volatile double product = (double)scratch[k] *
85 (
double)value[k * width + h * head_dim + d];
88 output[t * width + h * head_dim + d] = (float)(weighted / denominator);
int attention_full_token_major_f32_checked(const float *query, size_t query_elements, const float *key, size_t key_elements, const float *value, size_t value_elements, float *output, size_t output_elements, float *scratch, size_t scratch_bytes, size_t tokens, size_t heads, size_t head_dim)