v4.0 update. (#2371)
This commit is contained in:
@@ -118,7 +118,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
|
||||
using TensorStrideContiguousK = Stride<int, _1, Stride<int, int>>;
|
||||
using TensorStrideContiguousMN = Stride<_1, int, Stride<int, int>>;
|
||||
|
||||
|
||||
// compute S
|
||||
using CollectiveMmaKQ = typename cutlass::gemm::collective::CollectiveBuilder<
|
||||
cutlass::arch::Sm100, cutlass::arch::OpClassTensorOp,
|
||||
@@ -381,7 +381,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
make_tensor(args.mainloop.ptr_dq_acc, make_shape(Q, D, HB), args.mainloop.stride_dq_acc),
|
||||
SmemLayoutDQ{}(_, _, _0{})
|
||||
);
|
||||
|
||||
|
||||
return Params{
|
||||
args.problem_shape,
|
||||
args.mainloop,
|
||||
@@ -452,7 +452,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
|
||||
ThrMMA cta_mma_kq = TiledMmaKQ{}.get_slice(_0{});
|
||||
ThrMMA cta_mma_vdo = TiledMmaVDO{}.get_slice(_0{});
|
||||
|
||||
|
||||
auto tSTgK = cta_mma_kq.partition_A(gK);
|
||||
auto tSTgQ = cta_mma_kq.partition_B(gQ);
|
||||
auto tDPTgV = cta_mma_vdo.partition_A(gV);
|
||||
@@ -477,7 +477,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
group_modes<0,3>(sDO), group_modes<0,3>(tDPTgDO));
|
||||
|
||||
// set up lse and sum_odo
|
||||
|
||||
|
||||
auto [blk_coord_q, blk_coord_k, blk_coord_batch] = blk_coord;
|
||||
|
||||
pipeline_load_mma_q.producer_acquire(pipeline_load_mma_q_producer_state);
|
||||
@@ -495,7 +495,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
}
|
||||
|
||||
// load Q
|
||||
if (cute::elect_one_sync()) {
|
||||
if (cute::elect_one_sync()) {
|
||||
cute::copy(
|
||||
mainloop_params.tma_load_q.with(*tma_barrier, mcast_mask),
|
||||
tQgQ_mkl(_, iter_index, _0{}, blk_coord_batch),
|
||||
@@ -520,7 +520,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
&mLSE(gmem_idx, blk_coord_batch),
|
||||
gmem_idx < Q
|
||||
);
|
||||
|
||||
|
||||
pipeline_load_compute_lse.producer_commit(pipeline_load_compute_lse_producer_state, cutlass::arch::cpasync_barrier_arrive);
|
||||
++pipeline_load_compute_lse_producer_state;
|
||||
|
||||
@@ -529,7 +529,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
tma_barrier = pipeline_load_mma_do.producer_get_barrier(pipeline_load_mma_do_producer_state);
|
||||
|
||||
pipeline_load_mma_do.producer_expect_transaction(pipeline_load_mma_do_producer_state, kTransactionsBytesLoadV);
|
||||
|
||||
|
||||
// load V
|
||||
if (cute::elect_one_sync()) {
|
||||
cute::copy(
|
||||
@@ -540,7 +540,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
}
|
||||
|
||||
// load dO
|
||||
if (cute::elect_one_sync()) {
|
||||
if (cute::elect_one_sync()) {
|
||||
cute::copy(
|
||||
mainloop_params.tma_load_do.with(*tma_barrier, mcast_mask),
|
||||
tDOgDO_mkl(_, iter_index, _0{}, blk_coord_batch),
|
||||
@@ -573,7 +573,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
tma_barrier = pipeline_load_mma_q.producer_get_barrier(pipeline_load_mma_q_producer_state);
|
||||
|
||||
// load Q
|
||||
if (cute::elect_one_sync()) {
|
||||
if (cute::elect_one_sync()) {
|
||||
cute::copy(
|
||||
mainloop_params.tma_load_q.with(*tma_barrier, mcast_mask),
|
||||
tQgQ_mkl(_, iter_index, _0{}, blk_coord_batch),
|
||||
@@ -584,7 +584,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
++pipeline_load_mma_q_producer_state;
|
||||
|
||||
pipeline_load_compute_lse.producer_acquire(pipeline_load_compute_lse_producer_state);
|
||||
|
||||
|
||||
// load LSE
|
||||
smem_idx = TileShapeQ{} * pipeline_load_compute_lse_producer_state.index() + thread_idx * 4;
|
||||
gmem_idx = TileShapeQ{} * iter_index + thread_idx * 4;
|
||||
@@ -593,15 +593,15 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
&mLSE(gmem_idx, blk_coord_batch),
|
||||
gmem_idx < Q
|
||||
);
|
||||
|
||||
|
||||
pipeline_load_compute_lse.producer_commit(pipeline_load_compute_lse_producer_state, cutlass::arch::cpasync_barrier_arrive);
|
||||
++pipeline_load_compute_lse_producer_state;
|
||||
|
||||
pipeline_load_mma_do.producer_acquire(pipeline_load_mma_do_producer_state);
|
||||
tma_barrier = pipeline_load_mma_do.producer_get_barrier(pipeline_load_mma_do_producer_state);
|
||||
|
||||
// load dO
|
||||
if (cute::elect_one_sync()) {
|
||||
// load dO
|
||||
if (cute::elect_one_sync()) {
|
||||
cute::copy(
|
||||
mainloop_params.tma_load_do.with(*tma_barrier, mcast_mask),
|
||||
tDOgDO_mkl(_, iter_index, _0{}, blk_coord_batch),
|
||||
@@ -612,7 +612,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
++pipeline_load_mma_do_producer_state;
|
||||
|
||||
pipeline_load_compute_sum_odo.producer_acquire(pipeline_load_compute_sum_odo_producer_state);
|
||||
|
||||
|
||||
// load sum_OdO
|
||||
smem_idx = TileShapeQ{} * pipeline_load_compute_sum_odo_producer_state.index() + thread_idx * 4;
|
||||
gmem_idx = TileShapeQ{} * iter_index + thread_idx * 4;
|
||||
@@ -621,7 +621,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
&mSumOdO(gmem_idx, blk_coord_batch),
|
||||
gmem_idx < Q
|
||||
);
|
||||
|
||||
|
||||
pipeline_load_compute_sum_odo.producer_commit(pipeline_load_compute_sum_odo_producer_state, cutlass::arch::cpasync_barrier_arrive);
|
||||
++pipeline_load_compute_sum_odo_producer_state;
|
||||
|
||||
@@ -639,23 +639,23 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
int iter_count,
|
||||
MainloopArguments const& mainloop_args,
|
||||
TensorStorage& shared_tensors,
|
||||
PipelineLoadMmaQ& pipeline_load_mma_q,
|
||||
typename PipelineLoadMmaQ::PipelineState& pipeline_load_mma_q_consumer_state,
|
||||
PipelineLoadMmaDO& pipeline_load_mma_do,
|
||||
PipelineLoadMmaQ& pipeline_load_mma_q,
|
||||
typename PipelineLoadMmaQ::PipelineState& pipeline_load_mma_q_consumer_state,
|
||||
PipelineLoadMmaDO& pipeline_load_mma_do,
|
||||
typename PipelineLoadMmaDO::PipelineState& pipeline_load_mma_do_consumer_state,
|
||||
PipelineMmaComputeS& pipeline_mma_compute_s,
|
||||
PipelineMmaComputeS& pipeline_mma_compute_s,
|
||||
typename PipelineMmaComputeS::PipelineState& pipeline_mma_compute_s_producer_state,
|
||||
PipelineMmaComputeDP& pipeline_mma_compute_dp,
|
||||
PipelineMmaComputeDP& pipeline_mma_compute_dp,
|
||||
typename PipelineMmaComputeDP::PipelineState& pipeline_mma_compute_dp_producer_state,
|
||||
PipelineMmaReduceDQ& pipeline_mma_reduce_dq,
|
||||
PipelineMmaReduceDQ& pipeline_mma_reduce_dq,
|
||||
typename PipelineMmaReduceDQ::PipelineState& pipeline_mma_reduce_dq_producer_state,
|
||||
PipelineComputeMmaP& pipeline_compute_mma_p,
|
||||
PipelineComputeMmaP& pipeline_compute_mma_p,
|
||||
typename PipelineComputeMmaP::PipelineState& pipeline_compute_mma_p_consumer_state,
|
||||
PipelineComputeMmaDS& pipeline_compute_mma_ds,
|
||||
PipelineComputeMmaDS& pipeline_compute_mma_ds,
|
||||
typename PipelineComputeMmaDS::PipelineState& pipeline_compute_mma_ds_consumer_state,
|
||||
PipelineMmaComputeDKDV& pipeline_mma_compute_dkdv,
|
||||
typename PipelineMmaComputeDKDV::PipelineState& pipeline_mma_compute_dkdv_producer_state) {
|
||||
|
||||
|
||||
auto [Q, K, D, HB] = problem_shape;
|
||||
|
||||
auto sQ = make_tensor(make_smem_ptr(shared_tensors.smem_q.begin()), SmemLayoutQ{});
|
||||
@@ -685,7 +685,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
Tensor tDVrP = TiledMmaPDO::make_fragment_A(sP)(_, _, _, _0{});
|
||||
tDVrP.data() = TmemAllocation::kP;
|
||||
Tensor tDVrDOT = TiledMmaPDO::make_fragment_B(sDOT);
|
||||
|
||||
|
||||
TiledMmaKQ tiled_mma_kq;
|
||||
TiledMmaVDO tiled_mma_vdo;
|
||||
TiledMmaDSK tiled_mma_dsk;
|
||||
@@ -923,6 +923,8 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
TensorC const& coord,
|
||||
TensorShape const& tensor_shape) {
|
||||
|
||||
Tensor preds = cute::lazy::transform(coord, [&](auto const& c) { return elem_less(c, tensor_shape); });
|
||||
|
||||
auto copy_op = make_cotiled_copy(
|
||||
Copy_Atom<UniversalCopy<uint128_t>, Element>{},
|
||||
make_layout(make_shape(_1{}, Int<sizeof(uint128_t) / sizeof(Element)>{})),
|
||||
@@ -930,21 +932,11 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
);
|
||||
auto thr_copy = copy_op.get_slice(_0{});
|
||||
|
||||
auto tCg = thr_copy.partition_D(gmem);
|
||||
auto tCr = thr_copy.partition_S(quantize(regs));
|
||||
auto tCc = thr_copy.partition_D(coord);
|
||||
Tensor tCg = thr_copy.partition_D(gmem);
|
||||
Tensor tCr = thr_copy.partition_S(quantize(regs));
|
||||
Tensor tPc = thr_copy.partition_D(preds);
|
||||
|
||||
constexpr int R = decltype(tCr.layout())::rank;
|
||||
auto tCg_v = group_modes<1, R>(tCg);
|
||||
auto tCr_v = group_modes<1, R>(tCr);
|
||||
auto tCc_v = group_modes<1, R>(tCc);
|
||||
auto tCp_v = make_tensor<bool>(shape<1>(tCc_v));
|
||||
|
||||
for (int i = 0; i < size(tCp_v); ++i) {
|
||||
tCp_v(i) = elem_less(tCc_v(_0{},i), tensor_shape);
|
||||
}
|
||||
|
||||
copy_if(copy_op, tCp_v, tCr_v, tCg_v);
|
||||
copy_if(copy_op, tPc, tCr, tCg);
|
||||
}
|
||||
|
||||
|
||||
@@ -1073,7 +1065,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
PipelineMmaComputeDKDV& pipeline_mma_compute_dkdv,
|
||||
typename PipelineMmaComputeDKDV::PipelineState& pipeline_mma_compute_dkdv_consumer_state) {
|
||||
|
||||
|
||||
|
||||
auto [Q, K, D, HB] = problem_shape;
|
||||
|
||||
// in tmem, S & P overlap
|
||||
@@ -1114,7 +1106,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
Tensor tTR_cST = split_wg(thread_t2r.partition_D(cST));
|
||||
Tensor tTR_rST = make_tensor<ElementAcc>(shape(tTR_cST));
|
||||
Tensor tTR_tST = split_wg(thread_t2r.partition_S(tSTtST));
|
||||
|
||||
|
||||
Tensor tTR_cDPT_p = thread_t2r.partition_D(cDPT);
|
||||
Tensor tTR_cDPT = split_wg(tTR_cDPT_p);
|
||||
Tensor tTR_rDPT = make_tensor<ElementAcc>(shape(tTR_cDPT));
|
||||
@@ -1152,20 +1144,20 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
fn(cute::false_type{});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
dispatch_bool(std::is_base_of_v<cutlass::fmha::collective::CausalMask, Mask> &&
|
||||
warp_uniform(iter_index == get<1>(blk_coord)), [&](auto is_causal_masked_tile) {
|
||||
|
||||
// compute P = softmax(S, LSE)
|
||||
cute::copy(tiled_t2r, tTR_tST, tTR_rST);
|
||||
|
||||
|
||||
if constexpr (std::is_base_of_v<cutlass::fmha::collective::CausalMask, Mask> && decltype(is_causal_masked_tile)::value) {
|
||||
Mask{}.apply_mask(tTR_rST, [&](int i) {
|
||||
auto c_transpose = tTR_cST(i);
|
||||
return make_coord(get<1>(c_transpose) + iter_index * TileShapeQ{}, get<0>(c_transpose) + get<1>(blk_coord) * TileShapeK{});
|
||||
}, problem_shape);
|
||||
}
|
||||
|
||||
|
||||
ElementAcc log2_e = static_cast<ElementAcc>(M_LOG2E);
|
||||
float2 softmax_scale_log2_e;
|
||||
softmax_scale_log2_e.x = mainloop_args.softmax_scale * log2_e;
|
||||
@@ -1184,16 +1176,16 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
tTR_rST(i) = ::exp2f(out.x);
|
||||
tTR_rST(i+1) = ::exp2f(out.y);
|
||||
}
|
||||
|
||||
|
||||
auto tRT_rST = quantize(tTR_rST);
|
||||
auto tRT_rST_reshaped = make_tensor(tRT_rST.data(), shape(tRT_cST));
|
||||
|
||||
|
||||
cutlass::arch::fence_view_async_tmem_load();
|
||||
cutlass::arch::NamedBarrier(
|
||||
kNumComputeWarps * NumThreadsPerWarp,
|
||||
cutlass::arch::ReservedNamedBarriers::TransformBarrier
|
||||
).arrive_and_wait();
|
||||
|
||||
|
||||
cute::copy(tiled_r2t, tRT_rST_reshaped, tRT_tP);
|
||||
});
|
||||
|
||||
@@ -1293,9 +1285,9 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
typename PipelineMmaReduceDQ::PipelineState& pipeline_mma_reduce_dq_consumer_state,
|
||||
PipelineReduceTmaStore& pipeline_reduce_tma_store,
|
||||
typename PipelineReduceTmaStore::PipelineState& pipeline_reduce_tma_store_producer_state) {
|
||||
|
||||
|
||||
using X = Underscore;
|
||||
|
||||
|
||||
auto [Q, K, D, HB] = problem_shape;
|
||||
|
||||
auto [blk_coord_q, blk_coord_k, blk_coord_batch] = blk_coord;
|
||||
@@ -1307,7 +1299,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
tDQtDQ.data() = TmemAllocation::kDQ;
|
||||
|
||||
Tensor mDQ = mainloop_params.tma_red_dq.get_tma_tensor(make_shape(Q, D, HB));
|
||||
auto gDQ = local_tile(mDQ, TileShapeKQ{}, make_coord(_,_,_), Step<_1, _1, X>{})
|
||||
auto gDQ = local_tile(mDQ, TileShapeKQ{}, make_coord(_,_,_), Step<X, _1, _1>{})
|
||||
(_, _, _, _0{}, blk_coord_batch);
|
||||
|
||||
Tensor cDQ = make_identity_tensor(take<0,2>(TileShapeDSK{}));
|
||||
@@ -1376,7 +1368,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
iter_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CUTLASS_DEVICE void operator()(Params const& params, char* smem) {
|
||||
int warp_idx = cutlass::canonical_warp_idx_sync();
|
||||
@@ -1561,7 +1553,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
typename decltype(pipeline_compute_mma_p)::PipelineState pipeline_compute_mma_p_consumer_state;
|
||||
typename decltype(pipeline_compute_mma_ds)::PipelineState pipeline_compute_mma_ds_consumer_state;
|
||||
typename decltype(pipeline_mma_compute_dkdv)::PipelineState pipeline_mma_compute_dkdv_consumer_state;
|
||||
|
||||
|
||||
auto pipeline_load_mma_q_producer_state = make_producer_start_state<decltype(pipeline_load_mma_q)>();
|
||||
auto pipeline_load_mma_do_producer_state = make_producer_start_state<decltype(pipeline_load_mma_do)>();
|
||||
auto pipeline_load_compute_lse_producer_state = make_producer_start_state<decltype(pipeline_load_compute_lse)>();
|
||||
@@ -1587,7 +1579,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
|
||||
if (role == WarpRole::Load) {
|
||||
warpgroup_reg_set<RegisterAllocation::kLoad>();
|
||||
|
||||
|
||||
load(
|
||||
blk_coord,
|
||||
problem_shape,
|
||||
@@ -1596,7 +1588,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
params.mainloop,
|
||||
params.mainloop_params,
|
||||
shared_storage.tensors,
|
||||
pipeline_load_mma_q, pipeline_load_mma_q_producer_state,
|
||||
pipeline_load_mma_q, pipeline_load_mma_q_producer_state,
|
||||
pipeline_load_mma_do, pipeline_load_mma_do_producer_state,
|
||||
pipeline_load_compute_lse, pipeline_load_compute_lse_producer_state,
|
||||
pipeline_load_compute_sum_odo, pipeline_load_compute_sum_odo_producer_state
|
||||
@@ -1608,7 +1600,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
|
||||
tmem_allocator.allocate(TmemAllocator::Sm100TmemCapacityColumns, &shared_storage.tmem_base_ptr);
|
||||
__syncwarp();
|
||||
|
||||
|
||||
mma(
|
||||
blk_coord,
|
||||
problem_shape,
|
||||
@@ -1616,7 +1608,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
iter_count,
|
||||
params.mainloop,
|
||||
shared_storage.tensors,
|
||||
pipeline_load_mma_q, pipeline_load_mma_q_consumer_state,
|
||||
pipeline_load_mma_q, pipeline_load_mma_q_consumer_state,
|
||||
pipeline_load_mma_do, pipeline_load_mma_do_consumer_state,
|
||||
pipeline_mma_compute_s, pipeline_mma_compute_s_producer_state,
|
||||
pipeline_mma_compute_dp, pipeline_mma_compute_dp_producer_state,
|
||||
@@ -1629,7 +1621,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
}
|
||||
else if (role == WarpRole::Compute) {
|
||||
warpgroup_reg_set<RegisterAllocation::kCompute>();
|
||||
|
||||
|
||||
compute(
|
||||
blk_coord,
|
||||
problem_shape,
|
||||
@@ -1660,7 +1652,7 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
}
|
||||
else if (role == WarpRole::Reduce) {
|
||||
warpgroup_reg_set<RegisterAllocation::kReduce>();
|
||||
|
||||
|
||||
reduce(
|
||||
blk_coord,
|
||||
problem_shape,
|
||||
@@ -1677,9 +1669,9 @@ struct Sm100FmhaBwdKernelTmaWarpSpecialized {
|
||||
}
|
||||
else {
|
||||
warpgroup_reg_set<RegisterAllocation::kEmpty>();
|
||||
|
||||
|
||||
/* no-op */
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ struct Sm100FmhaFwdKernelTmaWarpspecialized {
|
||||
typename CollectiveMainloop::PipelineO::PipelineState pipeline_mma_corr_producer_state = cutlass::make_producer_start_state<typename CollectiveMainloop::PipelineO>();
|
||||
|
||||
CollectiveMainloop mainloop;
|
||||
CollectiveEpilogue epilogue;
|
||||
CollectiveEpilogue epilogue{params.epilogue};
|
||||
|
||||
if (role == WarpRole::Softmax0 || role == WarpRole::Softmax1) {
|
||||
warpgroup_reg_set<NumRegsSoftmax>();
|
||||
@@ -407,7 +407,8 @@ struct Sm100FmhaFwdKernelTmaWarpspecialized {
|
||||
pipeline_s0_corr, pipeline_s0_corr_consumer_state,
|
||||
pipeline_s1_corr, pipeline_s1_corr_consumer_state,
|
||||
pipeline_mma_corr, pipeline_mma_corr_consumer_state,
|
||||
pipeline_corr_epi, pipeline_corr_epi_producer_state
|
||||
pipeline_corr_epi, pipeline_corr_epi_producer_state,
|
||||
epilogue
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ struct Sm100FmhaMlaReductionKernel {
|
||||
ElementAcc sum_lse = 0;
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < kNLsePerThread; ++i) {
|
||||
sum_lse = sum_lse + expf(local_lse[i] - params.scale * lse_max);
|
||||
sum_lse = sum_lse + expf(local_lse[i] - lse_max);
|
||||
}
|
||||
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
@@ -156,7 +156,7 @@ struct Sm100FmhaMlaReductionKernel {
|
||||
|
||||
sum_lse = __shfl_sync(0xffffffff, sum_lse, 0);
|
||||
|
||||
ElementAcc global_lse = (sum_lse == 0.f || sum_lse != sum_lse) ? std::numeric_limits<ElementAcc>::infinity() : logf(sum_lse) + params.scale * lse_max;
|
||||
ElementAcc global_lse = (sum_lse == 0.f || sum_lse != sum_lse) ? std::numeric_limits<ElementAcc>::infinity() : logf(sum_lse) + lse_max;
|
||||
if (threadIdx.x == 0 and params.ptr_lse != nullptr) {
|
||||
gLSE(0) = global_lse;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user