@@ -66,6 +66,9 @@ static int choose_threads(int H) {
6666 return 512 ;
6767}
6868
69+ constexpr int RMSNORM_DW_ROWS_PER_CHUNK = 256 ;
70+ constexpr int RMSNORM_DW_H_TILE = 128 ;
71+
6972
7073template <typename scalar_t , typename weight_t >
7174__global__ void rmsnorm_fwd_kernel (
@@ -164,46 +167,48 @@ __global__ void rmsnorm_partial_dw_kernel(
164167 int T,
165168 int H
166169) {
167- int idx = blockIdx .x * blockDim .x + threadIdx .x ;
168- int total = T * H;
169-
170- if (idx >= total) return ;
171-
172- int row = idx / H;
173-
174- if (!mask[row]) {
175- partial_dw[idx] = 0 .0f ;
170+ int chunk = blockIdx .x ;
171+ int h = blockIdx .y * RMSNORM_DW_H_TILE + threadIdx .x ;
172+ if (h >= H) {
176173 return ;
177174 }
178175
179- float dyv = load_as_float<scalar_t >(dy + idx);
180- float xv = load_as_float<scalar_t >(x + idx);
181- float r = rstd[row];
176+ int t0 = chunk * RMSNORM_DW_ROWS_PER_CHUNK ;
177+ float acc = 0 .0f ;
178+
179+ #pragma unroll
180+ for (int i = 0 ; i < RMSNORM_DW_ROWS_PER_CHUNK ; ++i) {
181+ int row = t0 + i;
182+ float contrib = 0 .0f ;
183+ if (row < T && mask[row]) {
184+ int idx = row * H + h;
185+ float dyv = load_as_float<scalar_t >(dy + idx);
186+ float xv = load_as_float<scalar_t >(x + idx);
187+ contrib = dyv * xv * rstd[row];
188+ }
189+ acc += contrib;
190+ }
182191
183- partial_dw[idx] = dyv * xv * r ;
192+ partial_dw[chunk * H + h] = acc ;
184193}
185194
186195
187196__global__ void rmsnorm_reduce_dw_kernel (
188197 const float * __restrict__ partial_dw,
189198 float * __restrict__ dw,
190- int T ,
199+ int chunks ,
191200 int H
192201) {
193- int h = blockIdx .x ;
194- int tid = threadIdx .x ;
195-
196- float local_sum = 0 .0f ;
197-
198- for (int t = tid; t < T; t += blockDim .x ) {
199- local_sum += partial_dw[t * H + h];
202+ int h = blockIdx .x * RMSNORM_DW_H_TILE + threadIdx .x ;
203+ if (h >= H) {
204+ return ;
200205 }
201206
202- float sum = block_reduce_sum (local_sum);
203-
204- if (tid == 0 ) {
205- dw[h] = sum;
207+ float acc = 0 .0f ;
208+ for (int chunk = 0 ; chunk < chunks; ++chunk) {
209+ acc += partial_dw[chunk * H + h];
206210 }
211+ dw[h] = acc;
207212}
208213
209214
@@ -280,10 +285,10 @@ void rmsnorm_backward_partial_dw_cuda(
280285) {
281286 int T = x.size (0 );
282287 int H = x.size (1 );
283- int total = T * H;
284288
285- int threads = 256 ;
286- int blocks = (total + threads - 1 ) / threads;
289+ int chunks = (T + RMSNORM_DW_ROWS_PER_CHUNK - 1 ) / RMSNORM_DW_ROWS_PER_CHUNK ;
290+ dim3 blocks (chunks, (H + RMSNORM_DW_H_TILE - 1 ) / RMSNORM_DW_H_TILE );
291+ dim3 threads (RMSNORM_DW_H_TILE );
287292
288293 cudaStream_t stream = at::cuda::getCurrentCUDAStream ();
289294
@@ -305,18 +310,18 @@ void rmsnorm_backward_reduce_dw_cuda(
305310 torch::Tensor partial_dw,
306311 torch::Tensor dw
307312) {
308- int T = partial_dw.size (0 );
313+ int chunks = partial_dw.size (0 );
309314 int H = partial_dw.size (1 );
310315
311- int threads = choose_threads (T );
312- size_t smem = threads * sizeof ( float );
316+ dim3 blocks ((H + RMSNORM_DW_H_TILE - 1 ) / RMSNORM_DW_H_TILE );
317+ dim3 threads ( RMSNORM_DW_H_TILE );
313318
314319 cudaStream_t stream = at::cuda::getCurrentCUDAStream ();
315320
316- rmsnorm_reduce_dw_kernel<<<H , threads, smem , stream>>> (
321+ rmsnorm_reduce_dw_kernel<<<blocks , threads, 0 , stream>>> (
317322 partial_dw.data_ptr <float >(),
318323 dw.data_ptr <float >(),
319- T ,
324+ chunks ,
320325 H
321326 );
322327}
0 commit comments