Spaces:
Running on T4
Running on T4
Commit ·
7cdfc56
1
Parent(s): b3ca72d
- app.py +5 -2
- cuda/rwkv7_fast_ops_fp16.cu +152 -54
- 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
|
| 110 |
-
|
|
|
|
|
|
|
| 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
|
| 470 |
-
|
|
|
|
|
|
|
| 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 |
-
|
| 899 |
-
|
| 900 |
-
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
|
| 904 |
-
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
| 910 |
-
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
| 914 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 941 |
-
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
|
| 947 |
-
|
| 948 |
-
|
| 949 |
-
|
| 950 |
-
|
| 951 |
-
|
| 952 |
-
|
| 953 |
-
|
| 954 |
-
|
| 955 |
-
|
| 956 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 1302 |
-
|
| 1303 |
-
|
| 1304 |
-
|
| 1305 |
-
|
| 1306 |
-
|
| 1307 |
-
|
| 1308 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 1325 |
-
|
| 1326 |
-
|
| 1327 |
-
|
| 1328 |
-
|
| 1329 |
-
|
| 1330 |
-
|
| 1331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 20 |
using F = half;
|
| 21 |
#define CLONE_N 64
|
| 22 |
|
| 23 |
__device__ __forceinline__ float rotator1(int x) {
|
| 24 |
-
|
|
|
|
| 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 |
-
|
|
|
|
| 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 |
-
|
|
|
|
| 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>((
|
| 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 |
-
|
|
|
|
| 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);
|