skip to content
==> src/attend.c <==
1/* One head's attention for one query (mesh-ref gpt2.rs `attend_row`). */
2#include "mesh/ref/gpt2_attend.h"
3
4#include "mesh/ftz.h"
5#include "mesh/ref/block.h"
6#include "mesh/ref/gpt2_scalar.h"
7#include "mesh/ref/gpt2_shape.h"
8
9bool mesh_gpt2_attend_row(const float *q, size_t n, const float *k, size_t k_stride, const float *v,
10                          size_t v_stride, float *out) {
11    if (n > MESH_GPT2_CTX) return false;
12    float s[MESH_GPT2_CTX], e[MESH_GPT2_CTX], parts[MESH_GPT2_NT];
13    for (size_t j = 0; j < n; j++) {
14        const float *kj = k + j * k_stride;
15        float a = 0.0f;
16        for (int d = 0; d < MESH_GPT2_HEAD_DIM; d++) a = mesh_ftz_add(a, mesh_ftz_mul(q[d], kj[d]));
17        s[j] = mesh_ftz_mul(a, mesh_ftz_from_bits(MESH_GPT2_ATTN_SCALE_BITS));
18    }
19    for (size_t t = 0; t < MESH_GPT2_NT; t++) {
20        float m = mesh_block_max_f32_id();
21        for (size_t j = t; j < n; j += MESH_GPT2_NT) m = mesh_block_max_f32(m, s[j]);
22        parts[t] = m;
23    }
24    float m = mesh_block_reduce_f32(parts, MESH_GPT2_NT, mesh_block_max_f32_id(), mesh_block_max_f32);
25    for (size_t j = 0; j < n; j++) e[j] = mesh_gpt2_exp_poly(mesh_ftz_sub(s[j], m));
26    for (size_t t = 0; t < MESH_GPT2_NT; t++) {
27        float a = 0.0f;
28        for (size_t j = t; j < n; j += MESH_GPT2_NT) a = mesh_ftz_add(a, e[j]);
29        parts[t] = a;
30    }
31    float sum = mesh_block_reduce_f32(parts, MESH_GPT2_NT, mesh_block_sum_f32_id(), mesh_block_add_f32);
32    for (size_t j = 0; j < n; j++) e[j] = mesh_ftz_div(e[j], sum); /* e now holds p */
33    for (int d = 0; d < MESH_GPT2_HEAD_DIM; d++) {
34        float tot = 0.0f;
35        for (size_t g = 0; g < MESH_GPT2_PV_GROUPS; g++) {
36            float a = 0.0f;
37            for (size_t j = g; j < n; j += MESH_GPT2_PV_GROUPS) a = mesh_ftz_add(a, mesh_ftz_mul(e[j], v[j * v_stride + d]));
38            tot = g == 0 ? a : mesh_ftz_add(tot, a);
39        }
40        out[d] = tot;
41    }
42    return true;
43}