FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
adm_kernels.h
1#pragma once
2// Internal header — not part of the public API.
3// Shared constants, scratch-pointer struct, and host wrapper declarations
4// for the ADM (Adaptive Data Mapping) encode/decode kernels.
5
6#include "backend/types.h"
7#include <cstdint>
8#include <cstddef>
9
10namespace fz {
11namespace adm {
12
13// ── Shared constants ──────────────────────────────────────────────────────────
14
15// Block structure: 32 threads/warp × 16 elements/thread = 512 elements/warp-block.
16static constexpr int kBlockThreads = 32;
17static constexpr int kChunk = 16;
18static constexpr int kDecmpChunk = 32;
19static constexpr int kBlockElems = kBlockThreads * kChunk; // 512
20
21// Decoupled look-back prefix-sum limit (warps). Above this, Thrust fallback is used.
22static constexpr int kDecoupledMaxGsize = 1024;
23
24// Multi-warp-block redesign: group this many 32-thread "warp blocks" into one
25// CUDA thread block, so the decoupled look-back chain walks blocks (length
26// gsize/kWarpsPerBlock) instead of individual warps (length gsize). Profiling
27// (ncu) showed the decoupled kernel was ~7% achieved occupancy against a 50%
28// theoretical ceiling, with 63% of warp cycles stalled on the look-back's
29// memory-barrier spin — a latency/serialization problem, not a register or
30// local-memory-spill one (only 32 regs/thread, local_code/local_bits are
31// tiny). That profile is why this lever is expected to help here, unlike the
32// register-bound cuSZp3 compress kernels it's adapted from.
33static constexpr int kWarpsPerBlock = 8;
34
35inline size_t adm_num_blocks(size_t gsize) {
36 return (gsize + static_cast<size_t>(kWarpsPerBlock) - 1)
37 / static_cast<size_t>(kWarpsPerBlock);
38}
39
40// Center-relative shift (1 = code 1 means "equal to center").
41static constexpr int kShift = 1;
42
43// Maximum signal bytes per input element.
44static constexpr int kMaxSignalBytesU16 = 2;
45static constexpr int kMaxSignalBytesU32 = 4;
46
47// ── Size helpers ──────────────────────────────────────────────────────────────
48
49inline size_t adm_gsize(size_t n) {
50 return (n + static_cast<size_t>(kBlockElems) - 1) / kBlockElems;
51}
52
53inline size_t adm_flags_bytes(size_t gsize) {
54 return (gsize + 7) / 8;
55}
56
57inline size_t adm_flags_words(size_t gsize) {
58 return (adm_flags_bytes(gsize) + sizeof(uint32_t) - 1) / sizeof(uint32_t);
59}
60
61// ── Scratch pointer bundle ────────────────────────────────────────────────────
62// All pointers are pool-managed device allocations. The stage pre-allocates
63// them in onFinalize()/initScratch() and reuses them every execute() call.
64
65struct AdmScratch {
66 int* d_signal_length; // gsize × sizeof(int)
67 int* d_output_lengths; // (gsize+1) × sizeof(int)
68 void* d_centers; // gsize × sizeof(uint16_t or uint32_t)
69 uint32_t* d_block_flags; // adm_flags_words(gsize) × sizeof(uint32_t)
70 uint8_t* d_codes; // num_elements × 1
71 uint8_t* d_concat_signals; // num_elements × kMaxSignalBytes
72 uint8_t* d_bit_signals; // num_elements × kMaxSignalBytes (thrust path)
73 int* d_loc_offset; // (gsize+1) × sizeof(int) (decoupled path)
74 int* d_prefix_state; // (gsize+1) × sizeof(int) (decoupled path)
75 int* d_block_resolved; // (num_blocks+1) × sizeof(int) (decoupled path,
76 // block-level look-back "resolved" value —
77 // see kWarpsPerBlock)
78 unsigned int* d_overflow_flag; // 1 word; written by kernels only in debug builds
79};
80
81// ── u16 wrappers ──────────────────────────────────────────────────────────────
82
83void compress_u16(
84 const uint16_t* d_input, size_t num_elements,
85 uint8_t* d_output, size_t& output_size,
86 const AdmScratch& s, fz::stream_t stream);
87
88void decompress_u16(
89 const uint8_t* d_input, size_t input_size,
90 uint16_t* d_output, size_t num_elements,
91 const AdmScratch& s, fz::stream_t stream);
92
93size_t get_max_u16_payload_bytes(size_t num_elements);
94
95// ── u32 wrappers ──────────────────────────────────────────────────────────────
96
97void compress_u32(
98 const uint32_t* d_input, size_t num_elements,
99 uint8_t* d_output, size_t& output_size,
100 const AdmScratch& s, fz::stream_t stream);
101
102void decompress_u32(
103 const uint8_t* d_input, size_t input_size,
104 uint32_t* d_output, size_t num_elements,
105 const AdmScratch& s, fz::stream_t stream);
106
107size_t get_max_u32_payload_bytes(size_t num_elements);
108
109} // namespace adm
110} // namespace fz
Definition algorithms.h:48
Backend-neutral GPU type aliases.