@@ -1500,6 +1500,8 @@ torch::Tensor warp_copy_to_device(const std::vector<torch::Tensor> &data) {
15001500 return out;
15011501}
15021502
1503+ namespace specialized {
1504+
15031505torch::Tensor warp_glu_expert_bf16xf8_block_scal_16x16_fnuz (
15041506 const torch::Tensor &x,
15051507 const torch::Tensor &expert_ids,
@@ -1540,6 +1542,87 @@ torch::Tensor warp_glu_expert_bf16xf8_block_scal_16x16_fnuz(
15401542 return yb;
15411543}
15421544
1545+ std::tuple<torch::Tensor, torch::Tensor, torch::Tensor> warp_multi_head_latent_rope_bf16_v2 (
1546+ const torch::Tensor &qkv_act,
1547+ const torch::Tensor &cos_sin,
1548+ const torch::Tensor &positions,
1549+ const torch::Tensor &q_a_norm,
1550+ const torch::Tensor &kv_a_norm,
1551+ const torch::Tensor &q_b_proj,
1552+ const torch::Tensor &k_b_proj,
1553+ int64_t n_local_heads
1554+ ) {
1555+ auto x = qkv_act;
1556+ CHECK_CUDA (x);
1557+ CHECK_EQ (x.dtype (), torch::kBFloat16 );
1558+ CHECK_EQ (x.dim (), 3 );
1559+ CHECK_EQ (x.size (-1 ), 2112 );
1560+ CHECK_EQ (cos_sin.dtype (), torch::kInt64 );
1561+ CHECK_EQ (positions.dtype (), torch::kInt64 );
1562+
1563+ int batch = qkv_act.size (0 ), seqlen = qkv_act.size (1 );
1564+ int samples = batch * seqlen;
1565+
1566+ auto q = warp_rmsnorm_bf16 (x, q_a_norm, 1e-6f );
1567+ auto v_output = warp_rmsnorm_bf16 (x, kv_a_norm, 1e-6f , 1536 ); // [B, S, 512]
1568+ auto k_output = antares::ops::call (" rope_kt_bf16" , {v_output.view ({-1 , 8 , 64 }).view (torch::kInt32 ), cos_sin, x.view ({-1 , 33 , 64 }).view (torch::kInt32 ), positions}, {}).view (torch::kBFloat16 ).view ({batch, seqlen, 576 });
1569+
1570+ auto &w_q_b_proj = q_b_proj;
1571+ CHECK_EQ (w_q_b_proj.dtype (), torch::kBFloat16 );
1572+ CHECK_EQ (w_q_b_proj.dim (), 2 );
1573+ CHECK_EQ (k_b_proj.dtype (), torch::kBFloat16 );
1574+ CHECK_EQ (k_b_proj.dim (), 3 );
1575+ CHECK_CONTIGUOUS (k_b_proj.transpose (1 , 2 ));
1576+
1577+ auto q_output = torch::empty ({batch, seqlen, n_local_heads, 512 + 64 }, torch::TensorOptions ().dtype (q.dtype ()).device (q.device ()));
1578+ torch::Tensor qh = (IS_NVIDIA_GPU || samples >= 4 ) ? torch::matmul (q, w_q_b_proj.t ()).view ({samples, n_local_heads, -1 }) : \
1579+ antares::ops::call (" rope_gmv_bf16" , {q.view ({samples, -1 }).view (torch::kInt32 ), w_q_b_proj.view (torch::kInt32 )}, {}).view ({samples, n_local_heads, -1 }); // (BS, 1536) @ (3072, 1536)
1580+ auto buffer = q_output.flatten (0 , 1 ).transpose (0 , 1 ).narrow (-1 , 0 , 512 );
1581+ torch::matmul_out (buffer, qh.transpose (0 , 1 ).narrow (-1 , 0 , 128 ), k_b_proj);
1582+
1583+ antares::ops::call (" rope_qt_bf16_put" , {cos_sin, qh.view ({qh.size (0 ), -1 , 3 , 64 }).view (torch::kInt32 ), positions, q_output.view ({qh.size (0 ), -1 , 9 , 64 }).view (torch::kInt32 )}, {});
1584+ return {q_output, k_output, v_output};
1585+ }
1586+
1587+ torch::Tensor warp_gemm_nt_bf16xfp8_block_scal (const torch::Tensor &x, const torch::Tensor &w, const torch::Tensor &scal, int64_t policy = 0 ) {
1588+ CHECK_CUDA (x);
1589+ CHECK_EQ (x.dim (), 3 );
1590+ CHECK_EQ (x.dtype (), torch::kBFloat16 );
1591+ CHECK_EQ (w.dim (), 2 );
1592+
1593+ int samples = x.size (0 ) * x.size (1 );
1594+ if (w.dtype () == torch::kBFloat16 )
1595+ return torch::matmul (x.view ({samples, x.size (2 )}), w.t ()).view ({x.size (0 ), x.size (1 ), w.size (0 )});
1596+
1597+ if (scal.dim () == 1 ) {
1598+ CHECK_EQ (w.size (0 ), scal.size (0 ));
1599+ return antares::ops::call (" gemv_nt_bf16xfp8_row" , {x.view ({samples, x.size (2 )}).view (torch::kInt32 ), w.view (torch::kInt16 ), scal}, {}).view ({x.size (0 ), x.size (1 ), w.size (0 )});
1600+ }
1601+
1602+ CHECK_EQ (scal.dim (), 2 );
1603+ if (samples < 4 )
1604+ return antares::ops::call (" gemv_nt_bf16xfp8_block" , {x.view ({samples, x.size (2 )}).view (torch::kInt32 ), w.view (torch::kInt16 ), scal}, {}).view ({x.size (0 ), x.size (1 ), w.size (0 )});
1605+
1606+ torch::Tensor w_ = w;
1607+
1608+ if (policy == 0 ) {
1609+ static std::unordered_map<void *, torch::Tensor> cached;
1610+
1611+ auto dptr = scal.data_ptr ();
1612+ auto it = cached.find (dptr);
1613+ if (it == cached.end ()) {
1614+ cached[dptr] = antares::ops::call (" to_bfloat16_3d" , {w.unsqueeze (0 ), scal.unsqueeze (0 )}, {}).squeeze (0 );
1615+ it = cached.find (dptr);
1616+ }
1617+ w_ = it->second ;
1618+ } else {
1619+ w_ = antares::ops::call (" to_bfloat16_3d" , {w.unsqueeze (0 ), scal.unsqueeze (0 )}, {}).squeeze (0 );
1620+ }
1621+ return torch::matmul (x.view ({samples, x.size (2 )}), w_.t ()).view ({x.size (0 ), x.size (1 ), w.size (0 )});
1622+ }
1623+
1624+ }
1625+
15431626#endif
15441627
15451628
@@ -1576,7 +1659,9 @@ TORCH_LIBRARY(tutel_ops, m) {
15761659 m.def (" scatter_sample_ids" , warp_scatter_sample_ids);
15771660 m.def (" copy_to_device" , warp_copy_to_device);
15781661
1579- m.def (" glu_expert_bf16xf8_block_scal_16x16_fnuz" , warp_glu_expert_bf16xf8_block_scal_16x16_fnuz);
1662+ m.def (" multi_head_latent_rope_bf16_v2" , specialized::warp_multi_head_latent_rope_bf16_v2);
1663+ m.def (" glu_expert_bf16xf8_block_scal_16x16_fnuz" , specialized::warp_glu_expert_bf16xf8_block_scal_16x16_fnuz);
1664+ m.def (" gemm_nt_bf16xfp8_block_scal" , specialized::warp_gemm_nt_bf16xfp8_block_scal);
15801665#endif
15811666}
15821667#endif
0 commit comments