NeverlandPeter commited on
Commit
7cdfc56
·
1 Parent(s): b3ca72d
Files changed (3) hide show
  1. app.py +5 -2
  2. cuda/rwkv7_fast_ops_fp16.cu +152 -54
  3. cuda/rwkv7_wkv_fp16_v2.cu +18 -12
app.py CHANGED
@@ -21,8 +21,11 @@ RELEASE_PREFILL_CACHE = True # saves VRAM before decode; costs one sync/cache fl
21
 
22
  ########################## text rwkv ################################################################
23
 
24
- title = "rwkv7-g1h-7.2b-20260710-ctx10240"
25
- model_path = hf_hub_download(repo_id="BlinkDL/rwkv7-g1", filename=f"{title}.pth")
 
 
 
26
 
27
  v3a.MODEL_PATH = model_path
28
  v3a.WKV_MODE = "fp32io16" # use "fp16" to save WKV state VRAM, with lower precision
 
21
 
22
  ########################## text rwkv ################################################################
23
 
24
+ # title = "rwkv7-g1h-7.2b-20260710-ctx10240"
25
+ # model_path = hf_hub_download(repo_id="BlinkDL/rwkv7-g1", filename=f"{title}.pth")
26
+
27
+ title = "rwkv7-g1i_preview3260-7.2b-20260716-ctx12288"
28
+ model_path = hf_hub_download(repo_id="BlinkDL/temp-latest-training-models", filename=f"{title}.pth")
29
 
30
  v3a.MODEL_PATH = model_path
31
  v3a.WKV_MODE = "fp32io16" # use "fp16" to save WKV state VRAM, with lower precision
cuda/rwkv7_fast_ops_fp16.cu CHANGED
@@ -49,6 +49,7 @@ __device__ inline float sigmoid_fast(float x) {
49
  return 1.0f / (1.0f + __expf(-x));
50
  }
51
 
 
52
  __global__ void tmix_mix6_kernel(
53
  int T,
54
  int C,
@@ -106,11 +107,31 @@ __global__ void tmix_mix6_kernel(
106
  store_h2(out_a + idx, cur.x + dx0 * xa.x, cur.y + dx1 * xa.y);
107
  store_h2(out_g + idx, cur.x + dx0 * xg.x, cur.y + dx1 * xg.y);
108
 
109
- if (t == T - 1) {
110
- *reinterpret_cast<__half2*>(shift_state + static_cast<int64_t>(b) * C + c) = cur2;
 
 
111
  }
112
  }
113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  template <bool HalfMath, int Vec>
115
  __global__ void tmix_mix6_t1_c4096_kernel(
116
  const dtype* __restrict__ x,
@@ -439,6 +460,7 @@ __global__ void zero_vec4_kernel(dtype* __restrict__ out, int64_t n_vec4) {
439
  }
440
  }
441
 
 
442
  __global__ void cmix_mix_kernel(
443
  int T,
444
  int C,
@@ -466,8 +488,10 @@ __global__ void cmix_mix_kernel(
466
  const float2 mix = __half22float2(load_h2(x_k + c));
467
  store_h2(out + idx, cur.x + (prev.x - cur.x) * mix.x, cur.y + (prev.y - cur.y) * mix.y);
468
 
469
- if (t == T - 1) {
470
- *reinterpret_cast<__half2*>(shift_state + static_cast<int64_t>(b) * C + c) = cur2;
 
 
471
  }
472
  }
473
 
@@ -895,23 +919,46 @@ std::vector<at::Tensor> tmix_mix6_cuda(
895
  constexpr int threads = 256;
896
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
897
  auto stream = at::cuda::getCurrentCUDAStream();
898
- tmix_mix6_kernel<<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
899
- T, C,
900
- x.data_ptr<dtype>(),
901
- shift_state.data_ptr<dtype>(),
902
- x_r.data_ptr<dtype>(),
903
- x_w.data_ptr<dtype>(),
904
- x_k.data_ptr<dtype>(),
905
- x_v.data_ptr<dtype>(),
906
- x_a.data_ptr<dtype>(),
907
- x_g.data_ptr<dtype>(),
908
- out_r.data_ptr<dtype>(),
909
- out_w.data_ptr<dtype>(),
910
- out_k.data_ptr<dtype>(),
911
- out_v.data_ptr<dtype>(),
912
- out_a.data_ptr<dtype>(),
913
- out_g.data_ptr<dtype>(),
914
- total_pairs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
915
  C10_CUDA_KERNEL_LAUNCH_CHECK();
916
  return {out_r, out_w, out_k, out_v, out_a, out_g};
917
  }
@@ -937,23 +984,46 @@ std::vector<at::Tensor> tmix_mix6_cfg_cuda(
937
  auto out_g = at::empty_like(x);
938
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
939
  auto stream = at::cuda::getCurrentCUDAStream();
940
- tmix_mix6_kernel<<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
941
- T, C,
942
- x.data_ptr<dtype>(),
943
- shift_state.data_ptr<dtype>(),
944
- x_r.data_ptr<dtype>(),
945
- x_w.data_ptr<dtype>(),
946
- x_k.data_ptr<dtype>(),
947
- x_v.data_ptr<dtype>(),
948
- x_a.data_ptr<dtype>(),
949
- x_g.data_ptr<dtype>(),
950
- out_r.data_ptr<dtype>(),
951
- out_w.data_ptr<dtype>(),
952
- out_k.data_ptr<dtype>(),
953
- out_v.data_ptr<dtype>(),
954
- out_a.data_ptr<dtype>(),
955
- out_g.data_ptr<dtype>(),
956
- total_pairs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
957
  C10_CUDA_KERNEL_LAUNCH_CHECK();
958
  return {out_r, out_w, out_k, out_v, out_a, out_g};
959
  }
@@ -1298,14 +1368,28 @@ at::Tensor cmix_mix_cuda(
1298
  constexpr int threads = 256;
1299
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
1300
  auto stream = at::cuda::getCurrentCUDAStream();
1301
- cmix_mix_kernel<<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1302
- T,
1303
- C,
1304
- x.data_ptr<dtype>(),
1305
- shift_state.data_ptr<dtype>(),
1306
- x_k.data_ptr<dtype>(),
1307
- out.data_ptr<dtype>(),
1308
- total_pairs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1309
  C10_CUDA_KERNEL_LAUNCH_CHECK();
1310
  return out;
1311
  }
@@ -1321,14 +1405,28 @@ at::Tensor cmix_mix_cfg_cuda(
1321
  auto out = at::empty_like(x);
1322
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
1323
  auto stream = at::cuda::getCurrentCUDAStream();
1324
- cmix_mix_kernel<<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1325
- T,
1326
- C,
1327
- x.data_ptr<dtype>(),
1328
- shift_state.data_ptr<dtype>(),
1329
- x_k.data_ptr<dtype>(),
1330
- out.data_ptr<dtype>(),
1331
- total_pairs);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1332
  C10_CUDA_KERNEL_LAUNCH_CHECK();
1333
  return out;
1334
  }
 
49
  return 1.0f / (1.0f + __expf(-x));
50
  }
51
 
52
+ template <bool UpdateShift>
53
  __global__ void tmix_mix6_kernel(
54
  int T,
55
  int C,
 
107
  store_h2(out_a + idx, cur.x + dx0 * xa.x, cur.y + dx1 * xa.y);
108
  store_h2(out_g + idx, cur.x + dx0 * xg.x, cur.y + dx1 * xg.y);
109
 
110
+ if constexpr (UpdateShift) {
111
+ if (t == T - 1) {
112
+ *reinterpret_cast<__half2*>(shift_state + static_cast<int64_t>(b) * C + c) = cur2;
113
+ }
114
  }
115
  }
116
 
117
+ __global__ void update_shift_state_last_kernel(
118
+ int T,
119
+ int C,
120
+ const dtype* __restrict__ x,
121
+ dtype* __restrict__ shift_state,
122
+ int64_t total_pairs) {
123
+ const int64_t pair_idx = static_cast<int64_t>(blockIdx.x) * blockDim.x + threadIdx.x;
124
+ if (pair_idx >= total_pairs) {
125
+ return;
126
+ }
127
+
128
+ const int c_pairs = C >> 1;
129
+ const int b = static_cast<int>(pair_idx / c_pairs);
130
+ const int c = static_cast<int>(pair_idx - static_cast<int64_t>(b) * c_pairs) << 1;
131
+ const int64_t src_idx = (static_cast<int64_t>(b) * T + (T - 1)) * C + c;
132
+ *reinterpret_cast<__half2*>(shift_state + static_cast<int64_t>(b) * C + c) = load_h2(x + src_idx);
133
+ }
134
+
135
  template <bool HalfMath, int Vec>
136
  __global__ void tmix_mix6_t1_c4096_kernel(
137
  const dtype* __restrict__ x,
 
460
  }
461
  }
462
 
463
+ template <bool UpdateShift>
464
  __global__ void cmix_mix_kernel(
465
  int T,
466
  int C,
 
488
  const float2 mix = __half22float2(load_h2(x_k + c));
489
  store_h2(out + idx, cur.x + (prev.x - cur.x) * mix.x, cur.y + (prev.y - cur.y) * mix.y);
490
 
491
+ if constexpr (UpdateShift) {
492
+ if (t == T - 1) {
493
+ *reinterpret_cast<__half2*>(shift_state + static_cast<int64_t>(b) * C + c) = cur2;
494
+ }
495
  }
496
  }
497
 
 
919
  constexpr int threads = 256;
920
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
921
  auto stream = at::cuda::getCurrentCUDAStream();
922
+ if (T == 1) {
923
+ tmix_mix6_kernel<true><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
924
+ T, C,
925
+ x.data_ptr<dtype>(),
926
+ shift_state.data_ptr<dtype>(),
927
+ x_r.data_ptr<dtype>(),
928
+ x_w.data_ptr<dtype>(),
929
+ x_k.data_ptr<dtype>(),
930
+ x_v.data_ptr<dtype>(),
931
+ x_a.data_ptr<dtype>(),
932
+ x_g.data_ptr<dtype>(),
933
+ out_r.data_ptr<dtype>(),
934
+ out_w.data_ptr<dtype>(),
935
+ out_k.data_ptr<dtype>(),
936
+ out_v.data_ptr<dtype>(),
937
+ out_a.data_ptr<dtype>(),
938
+ out_g.data_ptr<dtype>(),
939
+ total_pairs);
940
+ } else {
941
+ tmix_mix6_kernel<false><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
942
+ T, C,
943
+ x.data_ptr<dtype>(),
944
+ shift_state.data_ptr<dtype>(),
945
+ x_r.data_ptr<dtype>(),
946
+ x_w.data_ptr<dtype>(),
947
+ x_k.data_ptr<dtype>(),
948
+ x_v.data_ptr<dtype>(),
949
+ x_a.data_ptr<dtype>(),
950
+ x_g.data_ptr<dtype>(),
951
+ out_r.data_ptr<dtype>(),
952
+ out_w.data_ptr<dtype>(),
953
+ out_k.data_ptr<dtype>(),
954
+ out_v.data_ptr<dtype>(),
955
+ out_a.data_ptr<dtype>(),
956
+ out_g.data_ptr<dtype>(),
957
+ total_pairs);
958
+ const int64_t state_pairs = static_cast<int64_t>(B) * (C / 2);
959
+ update_shift_state_last_kernel<<<static_cast<int>(ceil_div(state_pairs, threads)), threads, 0, stream>>>(
960
+ T, C, x.data_ptr<dtype>(), shift_state.data_ptr<dtype>(), state_pairs);
961
+ }
962
  C10_CUDA_KERNEL_LAUNCH_CHECK();
963
  return {out_r, out_w, out_k, out_v, out_a, out_g};
964
  }
 
984
  auto out_g = at::empty_like(x);
985
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
986
  auto stream = at::cuda::getCurrentCUDAStream();
987
+ if (T == 1) {
988
+ tmix_mix6_kernel<true><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
989
+ T, C,
990
+ x.data_ptr<dtype>(),
991
+ shift_state.data_ptr<dtype>(),
992
+ x_r.data_ptr<dtype>(),
993
+ x_w.data_ptr<dtype>(),
994
+ x_k.data_ptr<dtype>(),
995
+ x_v.data_ptr<dtype>(),
996
+ x_a.data_ptr<dtype>(),
997
+ x_g.data_ptr<dtype>(),
998
+ out_r.data_ptr<dtype>(),
999
+ out_w.data_ptr<dtype>(),
1000
+ out_k.data_ptr<dtype>(),
1001
+ out_v.data_ptr<dtype>(),
1002
+ out_a.data_ptr<dtype>(),
1003
+ out_g.data_ptr<dtype>(),
1004
+ total_pairs);
1005
+ } else {
1006
+ tmix_mix6_kernel<false><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1007
+ T, C,
1008
+ x.data_ptr<dtype>(),
1009
+ shift_state.data_ptr<dtype>(),
1010
+ x_r.data_ptr<dtype>(),
1011
+ x_w.data_ptr<dtype>(),
1012
+ x_k.data_ptr<dtype>(),
1013
+ x_v.data_ptr<dtype>(),
1014
+ x_a.data_ptr<dtype>(),
1015
+ x_g.data_ptr<dtype>(),
1016
+ out_r.data_ptr<dtype>(),
1017
+ out_w.data_ptr<dtype>(),
1018
+ out_k.data_ptr<dtype>(),
1019
+ out_v.data_ptr<dtype>(),
1020
+ out_a.data_ptr<dtype>(),
1021
+ out_g.data_ptr<dtype>(),
1022
+ total_pairs);
1023
+ const int64_t state_pairs = static_cast<int64_t>(B) * (C / 2);
1024
+ update_shift_state_last_kernel<<<static_cast<int>(ceil_div(state_pairs, threads)), threads, 0, stream>>>(
1025
+ T, C, x.data_ptr<dtype>(), shift_state.data_ptr<dtype>(), state_pairs);
1026
+ }
1027
  C10_CUDA_KERNEL_LAUNCH_CHECK();
1028
  return {out_r, out_w, out_k, out_v, out_a, out_g};
1029
  }
 
1368
  constexpr int threads = 256;
1369
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
1370
  auto stream = at::cuda::getCurrentCUDAStream();
1371
+ if (T == 1) {
1372
+ cmix_mix_kernel<true><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1373
+ T,
1374
+ C,
1375
+ x.data_ptr<dtype>(),
1376
+ shift_state.data_ptr<dtype>(),
1377
+ x_k.data_ptr<dtype>(),
1378
+ out.data_ptr<dtype>(),
1379
+ total_pairs);
1380
+ } else {
1381
+ cmix_mix_kernel<false><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1382
+ T,
1383
+ C,
1384
+ x.data_ptr<dtype>(),
1385
+ shift_state.data_ptr<dtype>(),
1386
+ x_k.data_ptr<dtype>(),
1387
+ out.data_ptr<dtype>(),
1388
+ total_pairs);
1389
+ const int64_t state_pairs = static_cast<int64_t>(B) * (C / 2);
1390
+ update_shift_state_last_kernel<<<static_cast<int>(ceil_div(state_pairs, threads)), threads, 0, stream>>>(
1391
+ T, C, x.data_ptr<dtype>(), shift_state.data_ptr<dtype>(), state_pairs);
1392
+ }
1393
  C10_CUDA_KERNEL_LAUNCH_CHECK();
1394
  return out;
1395
  }
 
1405
  auto out = at::empty_like(x);
1406
  const int64_t total_pairs = static_cast<int64_t>(B) * T * (C / 2);
1407
  auto stream = at::cuda::getCurrentCUDAStream();
1408
+ if (T == 1) {
1409
+ cmix_mix_kernel<true><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1410
+ T,
1411
+ C,
1412
+ x.data_ptr<dtype>(),
1413
+ shift_state.data_ptr<dtype>(),
1414
+ x_k.data_ptr<dtype>(),
1415
+ out.data_ptr<dtype>(),
1416
+ total_pairs);
1417
+ } else {
1418
+ cmix_mix_kernel<false><<<static_cast<int>(ceil_div(total_pairs, threads)), threads, 0, stream>>>(
1419
+ T,
1420
+ C,
1421
+ x.data_ptr<dtype>(),
1422
+ shift_state.data_ptr<dtype>(),
1423
+ x_k.data_ptr<dtype>(),
1424
+ out.data_ptr<dtype>(),
1425
+ total_pairs);
1426
+ const int64_t state_pairs = static_cast<int64_t>(B) * (C / 2);
1427
+ update_shift_state_last_kernel<<<static_cast<int>(ceil_div(state_pairs, threads)), threads, 0, stream>>>(
1428
+ T, C, x.data_ptr<dtype>(), shift_state.data_ptr<dtype>(), state_pairs);
1429
+ }
1430
  C10_CUDA_KERNEL_LAUNCH_CHECK();
1431
  return out;
1432
  }
cuda/rwkv7_wkv_fp16_v2.cu CHANGED
@@ -7,6 +7,7 @@
7
  #include <ATen/ATen.h>
8
  #include <ATen/cuda/CUDAContext.h>
9
  #include <cuda_fp16.h>
 
10
 
11
  namespace {
12
 
@@ -16,12 +17,13 @@ constexpr int LDG_ELEMS = sizeof(int4) / sizeof(half);
16
  constexpr float TWO_NEG_41 = 4.547473508864641e-13f;
17
  constexpr float NEXP_HALF_LOG2_E = -0.8750387749145276f;
18
  constexpr float NLOG2_E = -1.4426950408889634f;
19
- constexpr int ROT1 = static_cast<int>(2654435769);
20
  using F = half;
21
  #define CLONE_N 64
22
 
23
  __device__ __forceinline__ float rotator1(int x) {
24
- return TWO_NEG_41 * float(ROT1 * x);
 
25
  }
26
 
27
  __device__ __forceinline__ half w_delta(float w, int phase) {
@@ -109,7 +111,7 @@ __global__ void __launch_bounds__(CLONE_N, 2) wkv_fp16_v1_clone_kernel(
109
  state[j] = state_smem[i][lane ^ j];
110
  }
111
 
112
- __shared__ __align__(128) half2 r[CLONE_N / 2], k[CLONE_N / 2], w[CLONE_N / 2], a[CLONE_N / 2], bvec[CLONE_N / 2];
113
  #pragma unroll
114
  for (int tt = 0; tt < T; tt++) {
115
  int t = b * T * C + h * CLONE_N + tt * C;
@@ -117,7 +119,8 @@ __global__ void __launch_bounds__(CLONE_N, 2) wkv_fp16_v1_clone_kernel(
117
  clone_cp_async<4>((half2*)(i < 32 ? w : a) + lane, (half2*)((i < 32 ? w_ptr : a_ptr) + t) + lane, true);
118
  clone_cp_commit();
119
  clone_cp_async<4>((half2*)(i < 32 ? r : k) + lane, (half2*)((i < 32 ? r_ptr : k_ptr) + t) + lane, true);
120
- clone_cp_async<4>((half2*)bvec + lane, (half2*)(b_ptr + t) + lane, i < 32);
 
121
  clone_cp_commit();
122
 
123
  half vv = v_ptr[t + i];
@@ -197,6 +200,7 @@ __device__ __forceinline__ void prefetch_token(
197
  half2* k,
198
  half2* a,
199
  half2* b,
 
200
  const half* r_ptr,
201
  const half* w_ptr,
202
  const half* k_ptr,
@@ -205,7 +209,8 @@ __device__ __forceinline__ void prefetch_token(
205
  cp_async<4>((tid < 32 ? w : a) + lane, (const half2*)(tid < 32 ? w_ptr + token : a_ptr + token) + lane, true);
206
  cp_commit();
207
  cp_async<4>((tid < 32 ? r : k) + lane, (const half2*)(tid < 32 ? r_ptr + token : k_ptr + token) + lane, true);
208
- cp_async<4>(b + lane, (const half2*)(b_ptr + token) + lane, tid < 32);
 
209
  cp_commit();
210
  }
211
 
@@ -254,7 +259,7 @@ __global__ __launch_bounds__(N, 2) void wkv_fp16_v1_exact_kernel(
254
  state[j] = state_smem[i][lane ^ j];
255
  }
256
 
257
- __shared__ __align__(128) half2 r[HALF2_N], k[HALF2_N], w[HALF2_N], a[HALF2_N], bvec[HALF2_N];
258
  #pragma unroll
259
  for (int tt = 0; tt < T; tt++) {
260
  int t = b_id * T * C + h * N + tt * C;
@@ -262,7 +267,7 @@ __global__ __launch_bounds__(N, 2) void wkv_fp16_v1_exact_kernel(
262
  cp_async<4>((half2*)(i < 32 ? w : a) + lane, (half2*)((i < 32 ? w_ptr : a_ptr) + t) + lane, true);
263
  cp_commit();
264
  cp_async<4>((half2*)(i < 32 ? r : k) + lane, (half2*)((i < 32 ? r_ptr : k_ptr) + t) + lane, true);
265
- cp_async<4>((half2*)bvec + lane, (half2*)(b_ptr + t) + lane, i < 32);
266
  cp_commit();
267
 
268
  half vv = v_ptr[t + i];
@@ -350,9 +355,9 @@ __global__ __launch_bounds__(N, 2) void wkv_fp16_seq_v2_kernel(
350
  state[j] = state_smem[i][lane ^ j];
351
  }
352
 
353
- __shared__ __align__(128) half2 r[2][HALF2_N], w[2][HALF2_N], k[2][HALF2_N], a[2][HALF2_N], bvec[2][HALF2_N];
354
  int token = (b_id * T) * C + h * N;
355
- prefetch_token(i, lane, token, r[0], w[0], k[0], a[0], bvec[0], r_ptr, w_ptr, k_ptr, a_ptr, b_ptr);
356
 
357
  for (int tt = 0; tt < T; ++tt) {
358
  const int cur = tt & 1;
@@ -371,7 +376,7 @@ __global__ __launch_bounds__(N, 2) void wkv_fp16_seq_v2_kernel(
371
 
372
  if (tt + 1 < T) {
373
  int next_token = token + C;
374
- prefetch_token(i, lane, next_token, r[cur ^ 1], w[cur ^ 1], k[cur ^ 1], a[cur ^ 1], bvec[cur ^ 1], r_ptr, w_ptr, k_ptr, a_ptr, b_ptr);
375
  }
376
 
377
  half vv = v_ptr[token + i];
@@ -540,12 +545,13 @@ __global__ __launch_bounds__(N, 1) void wkv_fp16_one_cp_kernel(
540
  state[j] = state_smem[i][lane ^ j];
541
  }
542
 
543
- __shared__ __align__(128) half2 r[HALF2_N], w[HALF2_N], k[HALF2_N], a[HALF2_N], bvec[HALF2_N];
544
  const int token = b_id * C + h * N;
545
  cp_async<4>((half2*)(i < 32 ? w : a) + lane, (half2*)((i < 32 ? w_ptr : a_ptr) + token) + lane, true);
546
  cp_commit();
547
  cp_async<4>((half2*)(i < 32 ? r : k) + lane, (half2*)((i < 32 ? r_ptr : k_ptr) + token) + lane, true);
548
- cp_async<4>((half2*)bvec + lane, (half2*)(b_ptr + token) + lane, i < 32);
 
549
  cp_commit();
550
 
551
  half vv = __ldg(v_ptr + token + i);
 
7
  #include <ATen/ATen.h>
8
  #include <ATen/cuda/CUDAContext.h>
9
  #include <cuda_fp16.h>
10
+ #include <stdint.h>
11
 
12
  namespace {
13
 
 
17
  constexpr float TWO_NEG_41 = 4.547473508864641e-13f;
18
  constexpr float NEXP_HALF_LOG2_E = -0.8750387749145276f;
19
  constexpr float NLOG2_E = -1.4426950408889634f;
20
+ constexpr uint32_t ROT1 = 2654435769u;
21
  using F = half;
22
  #define CLONE_N 64
23
 
24
  __device__ __forceinline__ float rotator1(int x) {
25
+ const uint32_t bits = ROT1 * static_cast<uint32_t>(x);
26
+ return TWO_NEG_41 * static_cast<float>(static_cast<int32_t>(bits));
27
  }
28
 
29
  __device__ __forceinline__ half w_delta(float w, int phase) {
 
111
  state[j] = state_smem[i][lane ^ j];
112
  }
113
 
114
+ __shared__ __align__(128) half2 r[CLONE_N / 2], k[CLONE_N / 2], w[CLONE_N / 2], a[CLONE_N / 2], bvec[CLONE_N / 2], bvec_dummy[CLONE_N / 2];
115
  #pragma unroll
116
  for (int tt = 0; tt < T; tt++) {
117
  int t = b * T * C + h * CLONE_N + tt * C;
 
119
  clone_cp_async<4>((half2*)(i < 32 ? w : a) + lane, (half2*)((i < 32 ? w_ptr : a_ptr) + t) + lane, true);
120
  clone_cp_commit();
121
  clone_cp_async<4>((half2*)(i < 32 ? r : k) + lane, (half2*)((i < 32 ? r_ptr : k_ptr) + t) + lane, true);
122
+ // src-size 0 zero-fills, so warp 1 must not race warp 0's real bvec copy.
123
+ clone_cp_async<4>((i < 32 ? bvec : bvec_dummy) + lane, (half2*)(b_ptr + t) + lane, i < 32);
124
  clone_cp_commit();
125
 
126
  half vv = v_ptr[t + i];
 
200
  half2* k,
201
  half2* a,
202
  half2* b,
203
+ half2* b_dummy,
204
  const half* r_ptr,
205
  const half* w_ptr,
206
  const half* k_ptr,
 
209
  cp_async<4>((tid < 32 ? w : a) + lane, (const half2*)(tid < 32 ? w_ptr + token : a_ptr + token) + lane, true);
210
  cp_commit();
211
  cp_async<4>((tid < 32 ? r : k) + lane, (const half2*)(tid < 32 ? r_ptr + token : k_ptr + token) + lane, true);
212
+ // A predicated-off cp.async still zero-fills its shared destination.
213
+ cp_async<4>((tid < 32 ? b : b_dummy) + lane, (const half2*)(b_ptr + token) + lane, tid < 32);
214
  cp_commit();
215
  }
216
 
 
259
  state[j] = state_smem[i][lane ^ j];
260
  }
261
 
262
+ __shared__ __align__(128) half2 r[HALF2_N], k[HALF2_N], w[HALF2_N], a[HALF2_N], bvec[HALF2_N], bvec_dummy[HALF2_N];
263
  #pragma unroll
264
  for (int tt = 0; tt < T; tt++) {
265
  int t = b_id * T * C + h * N + tt * C;
 
267
  cp_async<4>((half2*)(i < 32 ? w : a) + lane, (half2*)((i < 32 ? w_ptr : a_ptr) + t) + lane, true);
268
  cp_commit();
269
  cp_async<4>((half2*)(i < 32 ? r : k) + lane, (half2*)((i < 32 ? r_ptr : k_ptr) + t) + lane, true);
270
+ cp_async<4>((i < 32 ? bvec : bvec_dummy) + lane, (half2*)(b_ptr + t) + lane, i < 32);
271
  cp_commit();
272
 
273
  half vv = v_ptr[t + i];
 
355
  state[j] = state_smem[i][lane ^ j];
356
  }
357
 
358
+ __shared__ __align__(128) half2 r[2][HALF2_N], w[2][HALF2_N], k[2][HALF2_N], a[2][HALF2_N], bvec[2][HALF2_N], bvec_dummy[HALF2_N];
359
  int token = (b_id * T) * C + h * N;
360
+ prefetch_token(i, lane, token, r[0], w[0], k[0], a[0], bvec[0], bvec_dummy, r_ptr, w_ptr, k_ptr, a_ptr, b_ptr);
361
 
362
  for (int tt = 0; tt < T; ++tt) {
363
  const int cur = tt & 1;
 
376
 
377
  if (tt + 1 < T) {
378
  int next_token = token + C;
379
+ prefetch_token(i, lane, next_token, r[cur ^ 1], w[cur ^ 1], k[cur ^ 1], a[cur ^ 1], bvec[cur ^ 1], bvec_dummy, r_ptr, w_ptr, k_ptr, a_ptr, b_ptr);
380
  }
381
 
382
  half vv = v_ptr[token + i];
 
545
  state[j] = state_smem[i][lane ^ j];
546
  }
547
 
548
+ __shared__ __align__(128) half2 r[HALF2_N], w[HALF2_N], k[HALF2_N], a[HALF2_N], bvec[HALF2_N], bvec_dummy[HALF2_N];
549
  const int token = b_id * C + h * N;
550
  cp_async<4>((half2*)(i < 32 ? w : a) + lane, (half2*)((i < 32 ? w_ptr : a_ptr) + token) + lane, true);
551
  cp_commit();
552
  cp_async<4>((half2*)(i < 32 ? r : k) + lane, (half2*)((i < 32 ? r_ptr : k_ptr) + token) + lane, true);
553
+ // bvec_dummy is correctness-critical: warp 1's src-size 0 copy writes zeros.
554
+ cp_async<4>((i < 32 ? bvec : bvec_dummy) + lane, (half2*)(b_ptr + token) + lane, i < 32);
555
  cp_commit();
556
 
557
  half vv = __ldg(v_ptr + token + i);