9#ifndef FZ_ANS_DIETGPU_ANS_BATCHPREFIXSUM_H
10#define FZ_ANS_DIETGPU_ANS_BATCHPREFIXSUM_H
16#include "utils/StaticUtils.h"
18namespace fz {
namespace ans {
22constexpr int kMaxBEPSThreads = 512;
26 __host__ __device__ __forceinline__ T operator()(
const T& v)
const {
31template <
typename T,
int Threads,
typename TransformFn>
32__global__
void batchExclusivePrefixSum1(
33 const T* __restrict__ in,
35 void* __restrict__ blockTotal,
36 uint32_t maxNumCompressedBlocks,
38 uint32_t batch = blockIdx.y;
39 uint32_t block = blockIdx.x;
40 uint32_t blocksInBatch = gridDim.x;
41 uint32_t tid = threadIdx.x;
43 int batchIdx = block * Threads + tid;
44 bool valid = batchIdx < maxNumCompressedBlocks;
45 int totalIdx = batch * maxNumCompressedBlocks + batchIdx;
46 auto v = valid ? fn(in[totalIdx]) : T(0);
48 using Scan = cub::BlockScan<T, Threads>;
49 __shared__
typename Scan::TempStorage smem;
52 Scan(smem).ExclusiveSum(v, prefix, total);
55 out[totalIdx] = prefix;
59 if (threadIdx.x == 0 && blockTotal) {
60 ((T*)blockTotal)[batch * blocksInBatch + block] = total;
65template <
typename T,
int Threads>
66__global__
void batchExclusivePrefixSum2(
67 void* __restrict__ blockTotal,
68 uint32_t maxNumCompressedBlocks,
69 uint32_t blocksInBatch) {
70 uint32_t batch = blockIdx.x;
71 uint32_t tid = threadIdx.x;
73 bool valid = tid < blocksInBatch;
74 auto v = valid ? ((T*)blockTotal)[batch * blocksInBatch + tid] : 0;
76 using Scan = cub::BlockScan<T, Threads>;
77 __shared__
typename Scan::TempStorage smem;
79 Scan(smem).ExclusiveSum(v, v);
82 ((T*)blockTotal)[batch * blocksInBatch + tid] = v;
86template <
typename T,
int Threads>
87__global__
void batchExclusivePrefixSum3(
89 const void* __restrict__ blockTotal,
90 uint32_t maxNumCompressedBlocks) {
91 uint32_t batch = blockIdx.y;
92 uint32_t block = blockIdx.x;
93 uint32_t blocksInBatch = gridDim.x;
94 uint32_t tid = threadIdx.x;
96 auto vBlock = ((
const T*)blockTotal)[batch * blocksInBatch + block];
98 int batchIdx = block * Threads + tid;
99 bool valid = batchIdx < maxNumCompressedBlocks;
101 int totalIdx = batch * maxNumCompressedBlocks + batchIdx;
104 out[totalIdx] += vBlock;
108inline size_t getBatchExclusivePrefixSumTempSize(
109 uint32_t maxNumCompressedBlocks) {
110 if (maxNumCompressedBlocks <= kMaxBEPSThreads) {
114 return divUp(maxNumCompressedBlocks, kMaxBEPSThreads);
119template <
typename T,
typename TransformFn>
120void batchExclusivePrefixSum(
124 uint32_t maxNumCompressedBlocks,
125 const TransformFn& fn,
126 cudaStream_t stream) {
128 assert(maxNumCompressedBlocks <= kMaxBEPSThreads * kMaxBEPSThreads);
130#define BPS_LEVEL_1(THREADS, TEMP) \
131 batchExclusivePrefixSum1<T, THREADS, TransformFn> \
132 <<<dim3(blocks, 1), THREADS, 0, stream>>>( \
133 in_dev, out_dev, TEMP, maxNumCompressedBlocks, fn)
135#define BPS_LEVEL_2(THREADS) \
136 batchExclusivePrefixSum2<T, THREADS> \
137 <<<1, THREADS, 0, stream>>>(temp_dev, maxNumCompressedBlocks, blocks)
139#define BPS_LEVEL_3(THREADS) \
140 batchExclusivePrefixSum3<T, THREADS> \
141 <<<dim3(blocks, 1), THREADS, 0, stream>>>( \
142 out_dev, temp_dev, maxNumCompressedBlocks)
144 if (maxNumCompressedBlocks > kMaxBEPSThreads) {
146 uint32_t blocks = divUp(maxNumCompressedBlocks, kMaxBEPSThreads);
150 BPS_LEVEL_1(kMaxBEPSThreads, temp_dev);
154 }
else if (blocks <= 64) {
156 }
else if (blocks <= 128) {
158 }
else if (blocks <= 256) {
161 assert(blocks <= kMaxBEPSThreads);
162 BPS_LEVEL_2(kMaxBEPSThreads);
165 BPS_LEVEL_3(kMaxBEPSThreads);
170 if (maxNumCompressedBlocks <= 32) {
171 BPS_LEVEL_1(32, (T*)
nullptr);
172 }
else if (maxNumCompressedBlocks <= 64) {
173 BPS_LEVEL_1(64, (T*)
nullptr);
174 }
else if (maxNumCompressedBlocks <= 128) {
175 BPS_LEVEL_1(128, (T*)
nullptr);
176 }
else if (maxNumCompressedBlocks <= 256) {
177 BPS_LEVEL_1(256, (T*)
nullptr);
179 assert(maxNumCompressedBlocks <= kMaxBEPSThreads);
180 BPS_LEVEL_1(kMaxBEPSThreads, (T*)
nullptr);