15 if (!x || rows <= 0 || dim <= 0 || head_dim <= 0) {
18 const int num_heads = dim / head_dim;
19 if (num_heads <= 0 || num_heads * head_dim != dim) {
23 for (
int row = 0; row < rows; ++row) {
24 float *row_ptr = x + (size_t) row * (
size_t) dim;
25 for (
int head = 0; head < num_heads; ++head) {
26 float *head_ptr = row_ptr + (size_t) head * (
size_t) head_dim;
28 for (
int col = 0; col < head_dim; ++col) {
29 sum_sq += (double) (head_ptr[col] * head_ptr[col]);
31 const float norm = sqrtf((
float) sum_sq);
32 const float inv_norm = 1.0f / fmaxf(norm, eps);
33 for (
int col = 0; col < head_dim; ++col) {
34 head_ptr[col] *= inv_norm;
47 if (!d_out || !x || !d_x || rows <= 0 || dim <= 0 || head_dim <= 0) {
50 const int num_heads = dim / head_dim;
51 if (num_heads <= 0 || num_heads * head_dim != dim) {
55 for (
int row = 0; row < rows; ++row) {
56 const float *d_row = d_out + (size_t) row * (
size_t) dim;
57 const float *x_row = x + (size_t) row * (
size_t) dim;
58 float *dx_row = d_x + (size_t) row * (
size_t) dim;
59 for (
int head = 0; head < num_heads; ++head) {
60 const float *d_head = d_row + (size_t) head * (
size_t) head_dim;
61 const float *x_head = x_row + (size_t) head * (
size_t) head_dim;
62 float *dx_head = dx_row + (size_t) head * (
size_t) head_dim;
66 for (
int col = 0; col < head_dim; ++col) {
67 sum_sq += (double) (x_head[col] * x_head[col]);
68 dot += (double) (d_head[col] * x_head[col]);
70 const float norm = sqrtf((
float) sum_sq);
71 const float inv_norm = 1.0f / fmaxf(norm, eps);
73 for (
int col = 0; col < head_dim; ++col) {
74 dx_head[col] = d_head[col] / eps;
78 const float proj_scale = inv_norm * inv_norm * inv_norm * (float) dot;
79 for (
int col = 0; col < head_dim; ++col) {
80 dx_head[col] = inv_norm * d_head[col] - proj_scale * x_head[col];
112 enum { ilp_factor = 4, num_levels = 4, vector_width = 8 };
113 const int vector_count = dim / vector_width;
114 const int cascade_count = vector_count / ilp_factor;
115 const int level_power =
119 const int level_step = 1 << level_power;
120 const int level_mask = level_step - 1;
121 __m256 acc[num_levels][ilp_factor];
122 for (
int level = 0; level < num_levels; ++level) {
123 for (
int lane = 0; lane < ilp_factor; ++lane) {
124 acc[level][lane] = _mm256_setzero_ps();
129 while (group + level_step <= cascade_count) {
130 for (
int offset = 0; offset < level_step; ++offset, ++group) {
131 for (
int lane = 0; lane < ilp_factor; ++lane) {
132 const int vector_index = group * ilp_factor + lane;
133 const __m256 value = _mm256_loadu_ps(
134 x + vector_index * vector_width);
135 const __m256 square = _mm256_mul_ps(value, value);
136 acc[0][lane] = _mm256_add_ps(acc[0][lane], square);
139 for (
int level = 1; level < num_levels; ++level) {
140 for (
int lane = 0; lane < ilp_factor; ++lane) {
142 _mm256_add_ps(acc[level][lane], acc[level - 1][lane]);
143 acc[level - 1][lane] = _mm256_setzero_ps();
145 const int mask = level_mask << (level * level_power);
146 if ((group &
mask) != 0) {
151 for (; group < cascade_count; ++group) {
152 for (
int lane = 0; lane < ilp_factor; ++lane) {
153 const int vector_index = group * ilp_factor + lane;
154 const __m256 value = _mm256_loadu_ps(
155 x + vector_index * vector_width);
156 const __m256 square = _mm256_mul_ps(value, value);
157 acc[0][lane] = _mm256_add_ps(acc[0][lane], square);
160 for (
int level = 1; level < num_levels; ++level) {
161 for (
int lane = 0; lane < ilp_factor; ++lane) {
163 _mm256_add_ps(acc[0][lane], acc[level][lane]);
167 int vector_index = cascade_count * ilp_factor;
168 for (; vector_index < vector_count; ++vector_index) {
169 const __m256 value = _mm256_loadu_ps(
170 x + vector_index * vector_width);
171 const __m256 square = _mm256_mul_ps(value, value);
172 acc[0][0] = _mm256_add_ps(acc[0][0], square);
174 for (
int lane = 1; lane < ilp_factor; ++lane) {
175 acc[0][0] = _mm256_add_ps(acc[0][0], acc[0][lane]);
178 _Alignas(32)
float lanes[8];
179 _mm256_store_ps(lanes, acc[0][0]);
180 volatile float sum = 0.0f;
181 for (
int lane = 0; lane < 8; ++lane) {
182 sum = sum + lanes[lane];
184 for (
int d = vector_count * vector_width; d < dim; ++d) {
185 sum = sum + x[d] * x[d];
190 volatile float sum = 0.0f;
191 for (
int d = 0; d < dim; ++d) {
192 sum = sum + x[d] * x[d];
203 if (!x || rows <= 0 || dim <= 0 || head_dim <= 0 ||
204 dim % head_dim != 0) {
207 const int num_heads = dim / head_dim;
208 for (
int row = 0; row < rows; ++row) {
209 float *row_ptr = x + (size_t)row * (
size_t)dim;
210 for (
int head = 0; head < num_heads; ++head) {
211 float *head_ptr = row_ptr + (size_t)head * (
size_t)head_dim;
214 const float inverse = 1.0f / sqrtf(sum + eps);
215#if defined(__AVX512F__)
216 const __m512 inv = _mm512_set1_ps(inverse);
218 for (; d + 16 <= head_dim; d += 16) {
221 _mm512_mul_ps(_mm512_loadu_ps(head_ptr + d), inv));
223 for (; d < head_dim; ++d) {
224 head_ptr[d] = head_ptr[d] * inverse;
226#elif defined(__AVX2__)
227 const __m256 inv = _mm256_set1_ps(inverse);
229 for (; d + 8 <= head_dim; d += 8) {
232 _mm256_mul_ps(_mm256_loadu_ps(head_ptr + d), inv));
234 for (; d < head_dim; ++d) {
235 head_ptr[d] = head_ptr[d] * inverse;
238 for (
int d = 0; d < head_dim; ++d) {
239 head_ptr[d] = head_ptr[d] * inverse;
262 __m256 streams[4] = {
263 _mm256_setzero_ps(), _mm256_setzero_ps(),
264 _mm256_setzero_ps(), _mm256_setzero_ps()
267 for (; d + 32 <= dim; d += 32) {
268 for (
int stream = 0; stream < 4; ++stream) {
269 _Alignas(32)
float lanes[8];
270 const __m256 values = _mm256_loadu_ps(x + d + stream * 8);
271 _mm256_store_ps(lanes, _mm256_mul_ps(values, values));
272 for (
int lane = 0; lane < 8; ++lane) {
277 _mm256_add_ps(streams[stream], _mm256_load_ps(lanes));
280 __m256 reduced = _mm256_add_ps(streams[0], streams[1]);
281 reduced = _mm256_add_ps(reduced, streams[2]);
282 reduced = _mm256_add_ps(reduced, streams[3]);
283 _Alignas(32)
float lanes[8];
284 _mm256_store_ps(lanes, reduced);
285 volatile float sum = 0.0f;
286 for (
int lane = 0; lane < 8; ++lane) {
287 sum = sum + lanes[lane];
289 for (; d < dim; ++d) {
298 volatile float sum = 0.0f;
299 for (
int d = 0; d < dim; ++d) {
314 if (!x || rows <= 0 || dim <= 0 || head_dim <= 0 ||
315 dim % head_dim != 0) {
318 const int num_heads = dim / head_dim;
319 if (expanded_heads <= 0 || expanded_heads % num_heads != 0) {
322 const int heads_per_group = expanded_heads / num_heads;
323 const int total_heads = rows * expanded_heads;
324 const int vector_limit = (total_heads / 32) * 32;
325 for (
int row = 0; row < rows; ++row) {
326 float *row_ptr = x + (size_t)row * (
size_t)dim;
327 for (
int head = 0; head < num_heads; ++head) {
329 row_ptr + (size_t)head * (
size_t)head_dim;
333 const float denominator =
342 const int flat_head =
343 (row * expanded_heads) + head * heads_per_group;
345 if (flat_head < vector_limit) {
358 for (
int col = 0; col < head_dim; ++col) {
void recurrent_qk_l2_norm_backward(const float *d_q_out, const float *d_k_out, const float *q, const float *k, float *d_q, float *d_k, int rows, int q_dim, int k_dim, int head_dim, float eps)