File size: 6,501 Bytes
85f86bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# Resident GPT-2 decode. Q4 source shapes follow HF Conv1D [input,output];
# the loader transposes to [output,input] before grouped asymmetric int4 quantization.
# wte/lm_head stays tied fp32; --fir-f32 restores all fp32 linears.
fir 1
model gpt2
config config.json
runtime graph
epsilon layer_norm_epsilon
prefix transformer.

# Config checks owned by this model file (a key that is absent passes).
require config model_type gpt2
require config activation_function gelu_new
require config scale_attn_weights true
require config scale_attn_by_inverse_layer_idx false
require config reorder_and_upcast_attn false
require config add_cross_attention false

# Every integer key of config.json is already a symbol (n_embd, n_head, ...).
# The graph runtime needs these names:
sym layers = n_layer
sym positions = n_positions
sym vocab = vocab_size
sym hidden = n_embd
sym nheads = n_head
sym headdim = hidden/nheads
sym mlp = 4*hidden
require sym hidden = nheads*headdim
buf token_id f32 1 input:token
buf position f32 1 input:position
buf x f32 n_embd
buf pos_embed f32 n_embd
buf norm f32 n_embd
buf qkv f32 3*n_embd
buf attn f32 n_embd
buf mix f32 n_embd
buf fc f32 mlp
buf activated f32 mlp
buf scores f32 n_head*n_positions
buf key_cache f32 n_positions*n_embd per_layer
buf value_cache f32 n_positions*n_embd per_layer
buf logits f32 vocab output:logits
weight wte f32 wte.weight tensor [vocab_size,n_embd]
weight wpe f32 wpe.weight tensor [n_positions,n_embd]
weight ln1w f32 h.{i}.ln_1.weight tensor [n_embd]
weight ln1b f32 h.{i}.ln_1.bias tensor [n_embd]
weight qkvw q4 h.{i}.attn.c_attn.weight tensor [n_embd,3*n_embd]
weight qkvb f32 h.{i}.attn.c_attn.bias tensor [3*n_embd]
weight attnw q4 h.{i}.attn.c_proj.weight tensor [n_embd,n_embd]
weight attnb f32 h.{i}.attn.c_proj.bias tensor [n_embd]
weight ln2w f32 h.{i}.ln_2.weight tensor [n_embd]
weight ln2b f32 h.{i}.ln_2.bias tensor [n_embd]
weight fcw q4 h.{i}.mlp.c_fc.weight tensor [n_embd,mlp]
weight fcb f32 h.{i}.mlp.c_fc.bias tensor [mlp]
weight projw q4 h.{i}.mlp.c_proj.weight tensor [mlp,n_embd]
weight projb f32 h.{i}.mlp.c_proj.bias tensor [n_embd]
weight lnfw f32 ln_f.weight tensor [n_embd]
weight lnfb f32 ln_f.bias tensor [n_embd]
# ---- Micro-kernels defined by this model --------------------------------------
# One line = one session_vm emit* call (mnemonic = emit name, lower case, no "emit").
# Registers r are 0..31; @inN / @outN / @buffer are element addresses in the arena.
# R0 holds the lane id on entry (rtou 0 0 copies it to U0).

kernel g2.add in=2 out=1 size=in0,in1,out0 threads=out0.size tg=1 tgbytes=16
  rtou 0 0
  uloadf32 1 0 @in0
  uloadf32 2 0 @in1
  add 1 1 2
  ustoref32 1 0 @out0
endkernel

# gelu_new(x) = x * sigmoid(2*sqrt(2/pi) * (x + 0.044715*x^3))
kernel g2.gelu_new in=1 out=1 size=in0,out0 threads=out0.size tg=1 tgbytes=16
  rtou 0 0
  uloadf32 1 0 @in0
  mul 2 1 1
  mul 2 2 1
  mulconst 2 2 0.044715
  add 2 2 1
  mulconst 2 2 2*sqrt(2/pi)
  sigmoid 2 2
  mul 1 1 2
  ustoref32 1 0 @out0
endkernel

# LayerNorm over one row: mean (R1), variance (R3), then (x-mean)*rsqrt(var+eps)*gamma+beta.
kernel g2.layernorm in=3 out=1 size=in0,in1,in2,out0 threads=1 tg=1 tgbytes=16
  loadconstf32 15 in0.size
  uconst 0 0
  loadconstf32 1 0
  forbegin 15
    uloadf32 2 0 @in0
    add 1 1 2
    uaddk 0 0 1
  forend
  mulconst 1 1 1/in0.size
  uconst 0 0
  loadconstf32 3 0
  forbegin 15
    uloadf32 2 0 @in0
    sub 2 2 1
    mul 2 2 2
    add 3 3 2
    uaddk 0 0 1
  forend
  mulconst 3 3 1/in0.size
  addconst 3 3 eps
  rsqrt 3 3
  uconst 0 0
  forbegin 15
    uloadf32 2 0 @in0
    uloadf32 4 0 @in1
    uloadf32 5 0 @in2
    sub 2 2 1
    mul 2 2 3
    mul 2 2 4
    add 2 2 5
    ustoref32 2 0 @out0
    uaddk 0 0 1
  forend
endkernel

# One lane per head: write this token's K/V into the cache, then causal softmax
# attention over positions 0..position (nothing after the current token is read).
# ins: qkv position key_cache value_cache scores; outs: attn key_cache value_cache scores.
kernel g2.attn_decode in=5 out=4 threads=nheads tg=1 tgbytes=16 expect=in0:3*hidden,in1:1,in2:positions*hidden,in3:positions*hidden,in4:nheads*positions,out0:hidden
  rtou 0 0
  umulk 1 0 headdim
  umulk 2 0 positions
  uconst 3 0
  uloadf32 14 3 @in1
  rtou 4 14
  umulk 4 4 hidden
  uadd 4 4 1
  addconst 14 14 1
  loadconstf32 15 headdim
  uaddk 5 1 0
  forbegin 15
    uloadf32 1 5 @in0+hidden
    uloadf32 2 5 @in0+2*hidden
    ustoref32 1 4 @in2
    ustoref32 2 4 @in3
    uaddk 4 4 1
    uaddk 5 5 1
  forend
  uaddk 4 1 0
  uaddk 6 2 0
  loadconstf32 10 -3e38
  forbegin 14
    uaddk 5 1 0
    loadconstf32 3 0
    forbegin 15
      uloadf32 1 5 @in0
      uloadf32 2 4 @in2
      mul 2 1 2
      add 3 3 2
      uaddk 4 4 1
      uaddk 5 5 1
    forend
    mulconst 3 3 1/sqrt(headdim)
    ustoref32 3 6 @in4
    cmplt 4 10 3
    ifbegin 4
      mulconst 10 3 1
    ifend
    uaddk 4 4 hidden-headdim
    uaddk 6 6 1
  forend
  uaddk 6 2 0
  loadconstf32 11 0
  forbegin 14
    uloadf32 3 6 @in4
    sub 3 3 10
    exp 3 3
    ustoref32 3 6 @in4
    add 11 11 3
    uaddk 6 6 1
  forend
  uaddk 6 2 0
  forbegin 14
    uloadf32 3 6 @in4
    div 3 3 11
    ustoref32 3 6 @in4
    uaddk 6 6 1
  forend
  uaddk 5 1 0
  forbegin 15
    uaddk 4 5 0
    uaddk 6 2 0
    loadconstf32 12 0
    forbegin 14
      uloadf32 1 6 @in4
      uloadf32 2 4 @in3
      mul 2 1 2
      add 12 12 2
      uaddk 4 4 hidden
      uaddk 6 6 1
    forend
    ustoref32 12 5 @out0
    uaddk 5 5 1
  forend
endkernel

node token ext fir.embedding token_id wte -> x
node positional ext fir.embedding position wpe -> pos_embed
node embeddings micro g2.add x pos_embed -> x
repeat layers
node ln1 micro g2.layernorm x ln1w ln1b -> norm
node qkv_linear ext fir.linear norm qkvw -> qkv
node qkv_bias micro g2.add qkv qkvb -> qkv
node attention micro g2.attn_decode qkv position key_cache value_cache scores -> attn key_cache value_cache scores
node attention_linear ext fir.linear attn attnw -> mix
node attention_bias micro g2.add mix attnb -> mix
node attention_residual micro g2.add x mix -> x
node ln2 micro g2.layernorm x ln2w ln2b -> norm
node fc_linear ext fir.linear norm fcw -> fc
node fc_bias micro g2.add fc fcb -> fc
node gelu micro g2.gelu_new fc -> activated
node proj_linear ext fir.linear activated projw -> mix
node proj_bias micro g2.add mix projb -> mix
node mlp_residual micro g2.add x mix -> x
endrepeat
node final_norm micro g2.layernorm x lnfw lnfb -> norm
node head ext fir.linear_t norm wte -> logits