beamgrad 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- beamgrad-2.0.0/CHANGELOG.md +264 -0
- beamgrad-2.0.0/CMakeLists.txt +259 -0
- beamgrad-2.0.0/LICENSE +21 -0
- beamgrad-2.0.0/MANIFEST.in +8 -0
- beamgrad-2.0.0/PKG-INFO +259 -0
- beamgrad-2.0.0/README.md +223 -0
- beamgrad-2.0.0/VERSION +1 -0
- beamgrad-2.0.0/abi/baseline-v0.5.symbols +72 -0
- beamgrad-2.0.0/abi/libdbs.symbols +78 -0
- beamgrad-2.0.0/cmake/beamgradConfig.cmake.in +7 -0
- beamgrad-2.0.0/cmake/dbs.map +4 -0
- beamgrad-2.0.0/cuda/dbs_cuda.cu +1395 -0
- beamgrad-2.0.0/cuda/dbs_cuda_stub.cpp +64 -0
- beamgrad-2.0.0/cuda/emulation/cuda_emulation.hpp +342 -0
- beamgrad-2.0.0/include/dbs.h +460 -0
- beamgrad-2.0.0/include/dbs_cuda.h +199 -0
- beamgrad-2.0.0/pkgconfig/dbs.pc.in +11 -0
- beamgrad-2.0.0/pyproject.toml +66 -0
- beamgrad-2.0.0/python/beamgrad/__init__.py +48 -0
- beamgrad-2.0.0/python/beamgrad/_build_info.py +4 -0
- beamgrad-2.0.0/python/beamgrad/_ctypes.py +205 -0
- beamgrad-2.0.0/python/beamgrad/_options.py +132 -0
- beamgrad-2.0.0/python/beamgrad/_search.py +424 -0
- beamgrad-2.0.0/python/beamgrad/_torch.py +468 -0
- beamgrad-2.0.0/python/beamgrad/_version.py +2 -0
- beamgrad-2.0.0/python/beamgrad/estimators.py +244 -0
- beamgrad-2.0.0/python/beamgrad/hf.py +187 -0
- beamgrad-2.0.0/python/beamgrad/jax.py +216 -0
- beamgrad-2.0.0/python/beamgrad/losses.py +128 -0
- beamgrad-2.0.0/python/beamgrad/py.typed +0 -0
- beamgrad-2.0.0/python/beamgrad.egg-info/PKG-INFO +259 -0
- beamgrad-2.0.0/python/beamgrad.egg-info/SOURCES.txt +47 -0
- beamgrad-2.0.0/python/beamgrad.egg-info/dependency_links.txt +1 -0
- beamgrad-2.0.0/python/beamgrad.egg-info/requires.txt +9 -0
- beamgrad-2.0.0/python/beamgrad.egg-info/top_level.txt +1 -0
- beamgrad-2.0.0/python/csrc/cpu_ops.cpp +445 -0
- beamgrad-2.0.0/python/csrc/cuda_ops.cpp +354 -0
- beamgrad-2.0.0/python/csrc/libdbs_module.cpp +13 -0
- beamgrad-2.0.0/setup.cfg +4 -0
- beamgrad-2.0.0/setup.py +130 -0
- beamgrad-2.0.0/src/c_api.cpp +1188 -0
- beamgrad-2.0.0/src/common.hpp +280 -0
- beamgrad-2.0.0/src/cpu_features.cpp +147 -0
- beamgrad-2.0.0/src/decoder.cpp +844 -0
- beamgrad-2.0.0/src/decoder.hpp +170 -0
- beamgrad-2.0.0/src/kernels.hpp +139 -0
- beamgrad-2.0.0/src/kernels_scalar.cpp +216 -0
- beamgrad-2.0.0/src/kernels_x86.cpp +206 -0
- beamgrad-2.0.0/src/penalty.hpp +124 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 2.0.0 (2026-09-25)
|
|
4
|
+
|
|
5
|
+
The project is renamed **beamgrad** (previously `differentiable-beam-search-cuda`
|
|
6
|
+
and the `dbs-torch` Python package). The C library keeps its name, `libdbs`,
|
|
7
|
+
and C ABI version 10. Every symbol of the 0.5 baseline is still exported;
|
|
8
|
+
three functions are added and one no-op stub is removed (see below).
|
|
9
|
+
|
|
10
|
+
### Highlights
|
|
11
|
+
|
|
12
|
+
- **Training a model through beam search.** `beamgrad.beam_search(step_fn,
|
|
13
|
+
options, max_steps)` runs an autoregressive model inside the search: each
|
|
14
|
+
step asks the model for the next-token distributions of the beams chosen so
|
|
15
|
+
far (with each beam's parent slot, to reorder a key/value cache), and the
|
|
16
|
+
returned scores are differentiable with respect to the model. Driving
|
|
17
|
+
Qwen2.5-0.5B and Qwen3-0.6B, it returns the same beams with bit-identical
|
|
18
|
+
scores as `transformers`' `generate(num_beams=...)` in float32, at the same
|
|
19
|
+
speed (`benchmarks/hf_beam_search.py`).
|
|
20
|
+
- **Training in bounded memory.** `beam_search`'s backward hands each step
|
|
21
|
+
only its own `[B, K]` path gradient, never a dense `[B, T, K, V]` one, and
|
|
22
|
+
`rescore_fn` takes the same gradient from one teacher-forced pass after a
|
|
23
|
+
search without an autograd graph. With activation checkpointing, a
|
|
24
|
+
Qwen2.5-0.5B training step at batch 8, 8 beams and 128 steps needs 1.7 GiB
|
|
25
|
+
above the weights instead of running out of memory on 16 GB
|
|
26
|
+
(`benchmarks/hf_training_memory.py`).
|
|
27
|
+
- **Losses, estimators and a controlled experiment.** `beamgrad.losses`
|
|
28
|
+
(structured margin, minimum risk) and `beamgrad.estimators`
|
|
29
|
+
(selected-beam softmax, relaxed top-k) in PyTorch, and a Multi30k
|
|
30
|
+
translation experiment comparing them with continued MLE over three seeds
|
|
31
|
+
(`experiments/multi30k`): minimum-risk training on the search's beams
|
|
32
|
+
improved test BLEU on every seed (+0.55 on average), and a margin against
|
|
33
|
+
the reference made it worse.
|
|
34
|
+
- **Wheels for every Python.** The extensions use only CPython's limited API,
|
|
35
|
+
so one wheel per PyTorch version and CUDA variant serves Python 3.10+.
|
|
36
|
+
Releases build them for PyTorch 2.13 and 2.14 on Linux (CPU, CUDA 12.6,
|
|
37
|
+
CUDA 13.0), macOS and Windows.
|
|
38
|
+
- **Native CUDA engine.** Beam search and its backward pass run entirely on
|
|
39
|
+
the GPU for beams up to 1024, with GNMT length penalty, EOS carry-forward,
|
|
40
|
+
`min_length` and variable-length batches. It selects the same beams, with
|
|
41
|
+
the same scores, as the CPU decoder. The PyTorch API no longer falls back
|
|
42
|
+
to the CPU for any option or beam size.
|
|
43
|
+
- **`beamgrad` Python package** with one device-agnostic API:
|
|
44
|
+
`final_scores` (autograd), `decode` (full trace, now on CPU too),
|
|
45
|
+
`backtrack`, and `steps=` for variable-length batches.
|
|
46
|
+
- **Tests that test.** The C++ tests used `assert()`, which Release builds
|
|
47
|
+
compile out, so CI had been running empty test bodies. They now always run.
|
|
48
|
+
The CUDA kernels are verified without a GPU by running the unmodified kernel
|
|
49
|
+
source through a CPU emulation layer, checked bit for bit against the CPU
|
|
50
|
+
decoder under several thread schedules.
|
|
51
|
+
- **Constraints everywhere.** Banned tokens, n-gram blocking and a repetition
|
|
52
|
+
penalty are available from Python on CPU, CUDA and JAX. Their per-beam token
|
|
53
|
+
sets are computed once per step instead of scanning the prefix for every
|
|
54
|
+
candidate (n-gram blocking at T=32, K=4, V=32k: 57 ms to 0.7 ms on CPU).
|
|
55
|
+
- **PyTorch integration.** The operators are registered with `torch.library`
|
|
56
|
+
(fake tensors, autograd, vmap), so `torch.compile`, `torch.export` and
|
|
57
|
+
`torch.vmap` work, and `final_scores` works under the `torch.func`
|
|
58
|
+
transforms (`grad`, `vjp`, `jacrev`, per-example gradients). Input
|
|
59
|
+
validation runs inside the decode kernels.
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- `beam_search(..., rescore_fn=, return_log_probs=)`: gradients by
|
|
64
|
+
teacher-forced re-scoring of the final beams, and control over keeping
|
|
65
|
+
the rows. `beamgrad.search` (scores, sequences and trace from one decode),
|
|
66
|
+
`sequence_scores`, `length_penalty`, and `BeamSearchResult.trace`.
|
|
67
|
+
- `beamgrad.losses`: `structured_margin`, `minimum_risk`, `matches`.
|
|
68
|
+
- `beamgrad.estimators`: `path_scores`, `selected_softmax` and
|
|
69
|
+
`relaxed_topk` (with each pool candidate's parent, token and origin),
|
|
70
|
+
matching the C library's surrogates on CPU and CUDA.
|
|
71
|
+
- `beamgrad.hf`: `CausalLMStep` (a step function for Hugging Face causal LMs,
|
|
72
|
+
with a key/value cache that follows the beams) and `CausalLMRescorer`
|
|
73
|
+
(chunked, checkpointed vocabulary projection; optional gradient
|
|
74
|
+
checkpointing).
|
|
75
|
+
- Operators `final_scores_path_gradient` and `length_penalty` (CPU and
|
|
76
|
+
CUDA), and their C/CUDA counterparts `dbs_cuda_path_gradient` and
|
|
77
|
+
`dbs_cuda_length_penalty`.
|
|
78
|
+
- `experiments/multi30k`, `benchmarks/hf_training_memory.py`, and the
|
|
79
|
+
guides `docs/training.md`, `docs/installation.md` and `docs/benchmarks.md`.
|
|
80
|
+
- Wheel builds (`.github/workflows/wheels.yml`), attached to GitHub releases;
|
|
81
|
+
`BEAMGRAD_PIN_TORCH` and `BEAMGRAD_LOCAL_VERSION` for building them.
|
|
82
|
+
- CI builds the CUDA operators with CUDA 12.4 (with PyTorch 2.4), 12.6 and
|
|
83
|
+
13.0 (with Blackwell architectures), and tests transformers with a
|
|
84
|
+
key/value cache, 384-step searches and autocast (bfloat16, float16).
|
|
85
|
+
- `beamgrad.beam_search`, `BeamState`, `BeamSearchResult`: beam search that
|
|
86
|
+
drives a model step by step, on CPU or CUDA, without stacking or copying the
|
|
87
|
+
per-step rows. `torch.ops.beamgrad.decode_step` (one step from an explicit
|
|
88
|
+
beam state), the C++ `BeamSearchDecoder::step`, and the CUDA C API's
|
|
89
|
+
`dbs_cuda_decode_step` / `DBSCudaBeamState` /
|
|
90
|
+
`dbs_cuda_decode_step_workspace_size` underneath; stepping through the rows
|
|
91
|
+
of a tensor selects exactly what the full decode selects.
|
|
92
|
+
- `examples/train_lm.py`: a GRU language model trained so that reference
|
|
93
|
+
sequences win beam search by a margin, and
|
|
94
|
+
`benchmarks/hf_beam_search.py`: parity, speed and training on a Hugging
|
|
95
|
+
Face causal LM against `generate`.
|
|
96
|
+
- `dbs_cuda_decode` / `dbs_cuda_backward` with workspace-size queries,
|
|
97
|
+
per-example metadata, constraints, NaN/`+inf` flags, optional trace outputs,
|
|
98
|
+
and asynchronous execution (`DBS_CUDA_SYNC_CHECK=1` synchronizes for
|
|
99
|
+
debugging).
|
|
100
|
+
- `dbs_decode_model_steps_ex`: incremental model-step decoding whose callback
|
|
101
|
+
learns each beam's parent slot, length, finished flag and token prefix (so a
|
|
102
|
+
model can reorder per-beam state), with optional constraints. The original
|
|
103
|
+
`dbs_decode_model_steps` also runs incrementally now (`T` callbacks instead
|
|
104
|
+
of re-decoding every prefix).
|
|
105
|
+
- `dbs_decode_batch_into` / `dbs_backward_batch_into`: batch decoding and the
|
|
106
|
+
final-score backward on caller-owned arrays, with per-example steps and
|
|
107
|
+
constraints, used by the PyTorch CPU operators and by JAX.
|
|
108
|
+
- `DBS_OK` / `DBS_ERROR_*` status constants.
|
|
109
|
+
- `BeamOptions.banned_tokens`, `no_repeat_ngram_size`, `repetition_penalty`;
|
|
110
|
+
`steps=` and `vmap` in `beamgrad.jax.final_scores`.
|
|
111
|
+
- An import-time check that beamgrad was compiled against the installed
|
|
112
|
+
PyTorch, with the command that fixes a mismatch.
|
|
113
|
+
- `beamgrad.BeamOptions`, `final_scores`, `decode`, `backtrack`,
|
|
114
|
+
`BeamSearchOutput`, `cuda_available`, `CUDA_MAX_BEAM`;
|
|
115
|
+
`beamgrad.jax.final_scores`.
|
|
116
|
+
- The wheel bundles libdbs as `beamgrad._libdbs` for ctypes and JAX use.
|
|
117
|
+
- CMake package `find_package(beamgrad)` with targets `beamgrad::dbs` and
|
|
118
|
+
`beamgrad::dbs_cuda`, a `DBS_WARNINGS_AS_ERRORS` option, and ctest targets
|
|
119
|
+
for the ABI symbol check, a pure-C header test and the C example.
|
|
120
|
+
- CI across Linux (GCC, Clang, static), macOS and Windows; sanitizers,
|
|
121
|
+
fuzzing, an nvcc build of the CUDA backend and Python CUDA operators; an
|
|
122
|
+
opt-in self-hosted GPU workflow; a release workflow with provenance
|
|
123
|
+
attestation.
|
|
124
|
+
- Documentation in `docs/`: algorithm, Python API, C API, CUDA engine,
|
|
125
|
+
development guide.
|
|
126
|
+
|
|
127
|
+
### Changed
|
|
128
|
+
|
|
129
|
+
- The Python extensions are built against CPython's limited API (abi3) and
|
|
130
|
+
no longer use pybind11.
|
|
131
|
+
- The CPU core is split into modules (decoder, kernels, dispatch, C ABI)
|
|
132
|
+
instead of one 4,300-line file. `src/c_api.cpp` includes `dbs.h` rather
|
|
133
|
+
than re-declaring it.
|
|
134
|
+
- `dbs_create_ex` rejects negative or non-finite options instead of silently
|
|
135
|
+
replacing them with defaults. Zero-initialised fields still select
|
|
136
|
+
defaults.
|
|
137
|
+
- The GNMT length penalty is evaluated in double precision from basic IEEE
|
|
138
|
+
operations (no `pow`) and rounded once, in a header the CPU and CUDA code
|
|
139
|
+
share, so the two agree bit for bit. Scores with `length_penalty_alpha != 0`
|
|
140
|
+
can differ from 1.x in the last bit.
|
|
141
|
+
- The softmax, dot product and sigmoid of the C-level surrogates are scalar on
|
|
142
|
+
every kernel path (the AVX-512 path used a different `exp`), and the core is
|
|
143
|
+
compiled without floating-point contraction, so results do not depend on
|
|
144
|
+
the SIMD path. The row scan keeps its SIMD paths, now for banned tokens and
|
|
145
|
+
EOS masking too, and a NEON path.
|
|
146
|
+
- Input validation (`validate_inputs`) checks every element of every row the
|
|
147
|
+
search reads, during the scan, in C, PyTorch (CPU and CUDA) and JAX.
|
|
148
|
+
Previously the C library sampled 1000 entries, JAX did not check at all, and
|
|
149
|
+
PyTorch made three extra passes over the tensor.
|
|
150
|
+
- The relaxed top-k pool is opt-in (`relaxed_pool_multiplier` defaults to 0):
|
|
151
|
+
keeping `8 * K` candidates per step made every decode pay for it
|
|
152
|
+
(K=64: 3.4 ms to 0.9 ms; K=256: 24 ms to 4 ms). `vocab_block` is ignored.
|
|
153
|
+
- Invalid arguments and inputs return `-1` as the header documents (they
|
|
154
|
+
returned `-2`), and every failing call records its own error message.
|
|
155
|
+
- CUDA: no kernel sorts a whole tile of candidates any more. Beams up to 16
|
|
156
|
+
use a register top-k scan, sized so that a single example still fills the
|
|
157
|
+
GPU; every scan, reduction and selection finds a block's best `K` keys with
|
|
158
|
+
a radix select and only the step's `K` winners are sorted. On an RTX 4080
|
|
159
|
+
SUPER a decode of B=8, T=16, V=32k takes 4.3 ms instead of 28.7 ms at K=64
|
|
160
|
+
(0.26 ms instead of 0.59 ms for B=1, K=4); results are unchanged, bit for
|
|
161
|
+
bit. The backward processes the beams of a step in parallel
|
|
162
|
+
(deterministically) instead of one thread per example.
|
|
163
|
+
- `dbs_decode_batch*` run on the calling thread as well and do not start
|
|
164
|
+
threads for a single example; variable batches read smaller beams in place
|
|
165
|
+
instead of copying them.
|
|
166
|
+
- PyTorch 2.4 or newer is required (for `torch.library.register_fake` and
|
|
167
|
+
`register_autograd`).
|
|
168
|
+
- SIMD scans pass candidates tied with the pool threshold to the exact
|
|
169
|
+
comparator, so every ISA path matches the scalar reference in all tie cases.
|
|
170
|
+
- `dbs_last_error` returns a thread-local copy, so the pointer stays valid if
|
|
171
|
+
another thread records an error on the same decoder.
|
|
172
|
+
- The CUDA API is reduced to `dbs_cuda_decode` / `dbs_cuda_backward` and is
|
|
173
|
+
asynchronous by default; its header carries export macros.
|
|
174
|
+
- Python 3.10 or newer is required.
|
|
175
|
+
- The C ABI's relaxed pool, `vocab_block` and status-code changes are listed
|
|
176
|
+
above; code that sets `relaxed_pool_multiplier` explicitly, or only checks
|
|
177
|
+
for a non-zero status, is unaffected.
|
|
178
|
+
|
|
179
|
+
### Fixed
|
|
180
|
+
|
|
181
|
+
- `beam_search(..., device="cuda")` rejected rows on `cuda:0`, because
|
|
182
|
+
`torch.device("cuda")` does not compare equal to `torch.device("cuda:0")`.
|
|
183
|
+
- Integers beyond 32 bits were truncated instead of rejected: `steps=[4,
|
|
184
|
+
2**32 + 1]` decoded one step for the second example (PyTorch on CPU and
|
|
185
|
+
CUDA, and JAX with 64-bit arrays), and through JAX's ctypes bindings
|
|
186
|
+
`min_length=2**32 + 1` became 1 and `no_repeat_ngram_size=2**32 + 1` became
|
|
187
|
+
1. Step counts are now range-checked before they are narrowed, non-integer
|
|
188
|
+
step counts are rejected, and `BeamOptions` rejects integer options outside
|
|
189
|
+
the 32-bit range.
|
|
190
|
+
- `torch.func.grad`, `vjp` and `jacrev` (and `vmap` of them) failed on
|
|
191
|
+
`final_scores`: the autograd formula registered with `torch.library` is an
|
|
192
|
+
`autograd.Function` without a separate `setup_context`, which `torch.func`
|
|
193
|
+
requires.
|
|
194
|
+
- The length penalty converted `length_penalty_alpha` to `int` before checking
|
|
195
|
+
its range, which is undefined behaviour for exponents beyond `INT_MAX`.
|
|
196
|
+
- `banned_tokens` cost a `[V]` Python list and its conversion to a tensor on
|
|
197
|
+
every PyTorch call (4 ms at V=128k); the mask is now scattered on the
|
|
198
|
+
target device.
|
|
199
|
+
- Backward rejected results whose beam size differed from the decoder's, so
|
|
200
|
+
examples of `dbs_decode_batch_variable` with their own beam sizes could not
|
|
201
|
+
be differentiated.
|
|
202
|
+
- `dbs_result_validate_deterministic_order` skipped the raw-score tie-break
|
|
203
|
+
and reported the decoder's own output as out of order (with a length
|
|
204
|
+
penalty and EOS).
|
|
205
|
+
- `dbs_allocator_counters_reset` zeroed the live byte count, which then went
|
|
206
|
+
negative as allocations were freed; it now resets only the call count.
|
|
207
|
+
- Early failures (null handle or output pointer) returned without recording
|
|
208
|
+
an error, so `dbs_last_global_error()` showed the previous call's message.
|
|
209
|
+
- `dbs_set_deterministic_seed` wrote the seed without synchronization.
|
|
210
|
+
- The CPU-only `libdbs_cuda` stub exported no symbols (hidden visibility and
|
|
211
|
+
no export macros) and lacked five declared functions, so linking against it
|
|
212
|
+
failed.
|
|
213
|
+
- The CUDA sparse backward attributed each final beam's gradient to the same
|
|
214
|
+
slot index at every step instead of following the beam's path, and used a
|
|
215
|
+
different estimator from the CPU. It is replaced by the exact path gradient.
|
|
216
|
+
- Typed and variable-batch decoding use overflow-checked size arithmetic.
|
|
217
|
+
- Batch decoding records errors in stats and reports real elapsed time.
|
|
218
|
+
- The JAX custom VJP no longer calls itself from its forward rule.
|
|
219
|
+
|
|
220
|
+
### Removed
|
|
221
|
+
|
|
222
|
+
- `dbs_validate_production_gate_manifest`, a stub that always failed.
|
|
223
|
+
- The test-only SIMD parity hooks, which were compiled into every build of the
|
|
224
|
+
library; the parity tests now live in `tests/internal_tests.cpp`.
|
|
225
|
+
- The `torch_dbs_extension`, `torch_dbs` and `jax_dbs` modules (use
|
|
226
|
+
`beamgrad`, `beamgrad._ctypes` and `beamgrad.jax`).
|
|
227
|
+
- `dbs_cuda_decode_forward*`, `dbs_cuda_decode_forward_variable`,
|
|
228
|
+
`dbs_cuda_backward_build_sparse` and `dbs_cuda_sparse_backward_scatter`
|
|
229
|
+
(use `dbs_cuda_decode` / `dbs_cuda_backward`); the
|
|
230
|
+
`DBS_ENABLE_SCORE_ONLY_FAST_PATH` switch and the `DBS_CUDA_USE_FAST_MATH`
|
|
231
|
+
option.
|
|
232
|
+
- Placeholder release material: SBOM/provenance templates, fixture manifests
|
|
233
|
+
and platform locks with `TBD` values, and the scripts built around them.
|
|
234
|
+
|
|
235
|
+
### Migrating from 1.x
|
|
236
|
+
|
|
237
|
+
| 1.x | 2.0 |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `pip install dbs-torch` | `pip install --no-build-isolation beamgrad` |
|
|
240
|
+
| `from torch_dbs_extension import DBSOptions, final_scores` | `from beamgrad import BeamOptions, final_scores` |
|
|
241
|
+
| `DBSOptions(beam_size=K, selected_temperature=..., ...)` | `BeamOptions(beam_size=K, eos_token=..., min_length=..., length_penalty_alpha=...)`; the other fields never affected `final_scores` |
|
|
242
|
+
| `torch_dbs_extension.decode(x, opts)` (CUDA only) | `beamgrad.decode(x, opts)` on CPU or CUDA |
|
|
243
|
+
| `DBS_BUILD_TORCH_CUDA=1` | automatic; force with `BEAMGRAD_CUDA=1` |
|
|
244
|
+
| `find_package(dbs)`, `dbs::dbs` | `find_package(beamgrad)`, `beamgrad::dbs` |
|
|
245
|
+
|
|
246
|
+
## 1.0.0
|
|
247
|
+
|
|
248
|
+
First stable release, as `dbs-torch` / `differentiable-beam-search-cuda`.
|
|
249
|
+
|
|
250
|
+
- C ABI version 10: hard beam search with deterministic ordering, GNMT length
|
|
251
|
+
penalty, EOS handling and minimum length; sparse (default) and capped dense
|
|
252
|
+
surrogate backward over final scores, selected-beam weights and a relaxed
|
|
253
|
+
top-k pool; batch and variable-length batch decoding; banned/forced tokens,
|
|
254
|
+
repetition penalty, n-gram blocking and token-filter callbacks; fp16/bf16
|
|
255
|
+
input; model-callback decoding with reusable workspaces; statistics and
|
|
256
|
+
JSON summaries.
|
|
257
|
+
- Runtime-dispatched AVX-512, AVX2, SSE4.2 and NEON kernels.
|
|
258
|
+
- PyTorch extension with CPU autograd and a CUDA forward kernel for beams up
|
|
259
|
+
to 32 (other cases ran on the CPU); ctypes and JAX wrappers.
|
|
260
|
+
|
|
261
|
+
## 0.x
|
|
262
|
+
|
|
263
|
+
Development releases leading to 1.0: the C ABI, sparse-by-default backward,
|
|
264
|
+
batching, constraints, SIMD kernels, and the first CUDA kernels.
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.20)
|
|
2
|
+
|
|
3
|
+
project(beamgrad
|
|
4
|
+
VERSION 2.0.0
|
|
5
|
+
DESCRIPTION "Differentiable beam search: C ABI, SIMD CPU kernels, and native CUDA"
|
|
6
|
+
HOMEPAGE_URL "https://github.com/maged15/beamgrad"
|
|
7
|
+
LANGUAGES C CXX)
|
|
8
|
+
|
|
9
|
+
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}" DBS_TOP_LEVEL)
|
|
10
|
+
|
|
11
|
+
option(DBS_BUILD_SHARED "Build shared libraries (static when OFF)" ON)
|
|
12
|
+
option(DBS_BUILD_TESTS "Build the test suite" ${DBS_TOP_LEVEL})
|
|
13
|
+
option(DBS_BUILD_BENCHMARKS "Build the C++ benchmark" ${DBS_TOP_LEVEL})
|
|
14
|
+
option(DBS_BUILD_FUZZER "Build the libFuzzer harness (Clang only)" OFF)
|
|
15
|
+
option(DBS_ENABLE_CUDA "Build the native CUDA backend (otherwise a stub is built)" OFF)
|
|
16
|
+
option(DBS_ENABLE_SANITIZERS "Build with AddressSanitizer and UndefinedBehaviorSanitizer" OFF)
|
|
17
|
+
option(DBS_ENABLE_TSAN "Build with ThreadSanitizer" OFF)
|
|
18
|
+
option(DBS_WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF)
|
|
19
|
+
|
|
20
|
+
# The C ABI version is the shared-library SOVERSION; it changes only on
|
|
21
|
+
# binary-incompatible changes (see docs/c-api.md).
|
|
22
|
+
set(DBS_ABI_VERSION 10)
|
|
23
|
+
|
|
24
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
25
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
26
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
27
|
+
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
|
28
|
+
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
|
29
|
+
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
30
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
31
|
+
endif()
|
|
32
|
+
|
|
33
|
+
include(GNUInstallDirs)
|
|
34
|
+
|
|
35
|
+
if(DBS_ENABLE_SANITIZERS AND NOT MSVC)
|
|
36
|
+
add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=undefined)
|
|
37
|
+
add_link_options(-fsanitize=address,undefined)
|
|
38
|
+
endif()
|
|
39
|
+
if(DBS_ENABLE_TSAN AND NOT MSVC)
|
|
40
|
+
add_compile_options(-fsanitize=thread -fno-omit-frame-pointer)
|
|
41
|
+
add_link_options(-fsanitize=thread)
|
|
42
|
+
endif()
|
|
43
|
+
|
|
44
|
+
# Floating-point contraction (fused multiply-add) would let compilers round
|
|
45
|
+
# differently on different targets; results must not depend on the target.
|
|
46
|
+
function(dbs_set_fp_model target)
|
|
47
|
+
if(NOT MSVC)
|
|
48
|
+
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-ffp-contract=off>)
|
|
49
|
+
endif()
|
|
50
|
+
endfunction()
|
|
51
|
+
|
|
52
|
+
function(dbs_set_warnings target)
|
|
53
|
+
if(MSVC)
|
|
54
|
+
target_compile_options(${target} PRIVATE /W4 /permissive-)
|
|
55
|
+
if(DBS_WARNINGS_AS_ERRORS)
|
|
56
|
+
target_compile_options(${target} PRIVATE /WX)
|
|
57
|
+
endif()
|
|
58
|
+
else()
|
|
59
|
+
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wall -Wextra -Wpedantic>)
|
|
60
|
+
if(DBS_WARNINGS_AS_ERRORS)
|
|
61
|
+
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Werror>)
|
|
62
|
+
endif()
|
|
63
|
+
endif()
|
|
64
|
+
endfunction()
|
|
65
|
+
|
|
66
|
+
if(DBS_BUILD_SHARED)
|
|
67
|
+
set(DBS_LIBRARY_TYPE SHARED)
|
|
68
|
+
else()
|
|
69
|
+
set(DBS_LIBRARY_TYPE STATIC)
|
|
70
|
+
endif()
|
|
71
|
+
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
# libdbs: CPU decoder and C ABI
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
set(DBS_CORE_SOURCES
|
|
77
|
+
src/c_api.cpp
|
|
78
|
+
src/cpu_features.cpp
|
|
79
|
+
src/decoder.cpp
|
|
80
|
+
src/kernels_scalar.cpp
|
|
81
|
+
src/kernels_x86.cpp)
|
|
82
|
+
|
|
83
|
+
# Object library so the internal tests can link the implementation directly.
|
|
84
|
+
add_library(dbs_core_objects OBJECT ${DBS_CORE_SOURCES})
|
|
85
|
+
set_target_properties(dbs_core_objects PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
86
|
+
target_include_directories(dbs_core_objects PRIVATE include src)
|
|
87
|
+
if(DBS_BUILD_SHARED)
|
|
88
|
+
target_compile_definitions(dbs_core_objects PRIVATE DBS_BUILD_SHARED DBS_COMPILING_LIBRARY)
|
|
89
|
+
else()
|
|
90
|
+
target_compile_definitions(dbs_core_objects PRIVATE DBS_STATIC)
|
|
91
|
+
endif()
|
|
92
|
+
dbs_set_warnings(dbs_core_objects)
|
|
93
|
+
dbs_set_fp_model(dbs_core_objects)
|
|
94
|
+
|
|
95
|
+
add_library(dbs ${DBS_LIBRARY_TYPE} $<TARGET_OBJECTS:dbs_core_objects>)
|
|
96
|
+
add_library(beamgrad::dbs ALIAS dbs)
|
|
97
|
+
target_include_directories(dbs PUBLIC
|
|
98
|
+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
|
99
|
+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
|
100
|
+
find_package(Threads REQUIRED)
|
|
101
|
+
target_link_libraries(dbs PRIVATE Threads::Threads)
|
|
102
|
+
if(DBS_BUILD_SHARED)
|
|
103
|
+
target_compile_definitions(dbs INTERFACE DBS_BUILD_SHARED)
|
|
104
|
+
set_target_properties(dbs PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${DBS_ABI_VERSION})
|
|
105
|
+
if(UNIX AND NOT APPLE)
|
|
106
|
+
target_link_options(dbs PRIVATE "-Wl,--version-script=${PROJECT_SOURCE_DIR}/cmake/dbs.map")
|
|
107
|
+
endif()
|
|
108
|
+
else()
|
|
109
|
+
target_compile_definitions(dbs INTERFACE DBS_STATIC)
|
|
110
|
+
endif()
|
|
111
|
+
|
|
112
|
+
# ---------------------------------------------------------------------------
|
|
113
|
+
# libdbs_cuda: native CUDA backend, or a stub that reports "unavailable"
|
|
114
|
+
# ---------------------------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
if(DBS_ENABLE_CUDA)
|
|
117
|
+
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
|
|
118
|
+
set(CMAKE_CUDA_ARCHITECTURES 75 80 86 89 90)
|
|
119
|
+
endif()
|
|
120
|
+
enable_language(CUDA)
|
|
121
|
+
add_library(dbs_cuda ${DBS_LIBRARY_TYPE} cuda/dbs_cuda.cu)
|
|
122
|
+
set_target_properties(dbs_cuda PROPERTIES
|
|
123
|
+
CUDA_STANDARD 17
|
|
124
|
+
CUDA_STANDARD_REQUIRED ON
|
|
125
|
+
CUDA_VISIBILITY_PRESET hidden
|
|
126
|
+
POSITION_INDEPENDENT_CODE ON)
|
|
127
|
+
else()
|
|
128
|
+
add_library(dbs_cuda ${DBS_LIBRARY_TYPE} cuda/dbs_cuda_stub.cpp)
|
|
129
|
+
dbs_set_warnings(dbs_cuda)
|
|
130
|
+
endif()
|
|
131
|
+
add_library(beamgrad::dbs_cuda ALIAS dbs_cuda)
|
|
132
|
+
target_include_directories(dbs_cuda
|
|
133
|
+
PUBLIC
|
|
134
|
+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
|
135
|
+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
136
|
+
PRIVATE src)
|
|
137
|
+
if(DBS_BUILD_SHARED)
|
|
138
|
+
target_compile_definitions(dbs_cuda PRIVATE DBS_BUILD_SHARED DBS_COMPILING_LIBRARY INTERFACE DBS_BUILD_SHARED)
|
|
139
|
+
set_target_properties(dbs_cuda PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${DBS_ABI_VERSION})
|
|
140
|
+
else()
|
|
141
|
+
target_compile_definitions(dbs_cuda PUBLIC DBS_STATIC)
|
|
142
|
+
endif()
|
|
143
|
+
|
|
144
|
+
# ---------------------------------------------------------------------------
|
|
145
|
+
# Tests, benchmark, fuzzer
|
|
146
|
+
# ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
if(DBS_BUILD_TESTS)
|
|
149
|
+
enable_testing()
|
|
150
|
+
|
|
151
|
+
add_executable(dbs_tests tests/dbs_tests.cpp)
|
|
152
|
+
target_link_libraries(dbs_tests PRIVATE dbs)
|
|
153
|
+
dbs_set_warnings(dbs_tests)
|
|
154
|
+
add_test(NAME dbs_tests COMMAND dbs_tests)
|
|
155
|
+
|
|
156
|
+
add_executable(dbs_internal_tests tests/internal_tests.cpp $<TARGET_OBJECTS:dbs_core_objects>)
|
|
157
|
+
target_include_directories(dbs_internal_tests PRIVATE include src tests)
|
|
158
|
+
target_compile_definitions(dbs_internal_tests PRIVATE DBS_STATIC)
|
|
159
|
+
target_link_libraries(dbs_internal_tests PRIVATE Threads::Threads)
|
|
160
|
+
dbs_set_warnings(dbs_internal_tests)
|
|
161
|
+
dbs_set_fp_model(dbs_internal_tests)
|
|
162
|
+
add_test(NAME dbs_internal_tests COMMAND dbs_internal_tests)
|
|
163
|
+
|
|
164
|
+
# Both public headers must be valid C, and both libraries must export them.
|
|
165
|
+
add_executable(dbs_c_api_test tests/c_api_test.c)
|
|
166
|
+
target_link_libraries(dbs_c_api_test PRIVATE dbs dbs_cuda)
|
|
167
|
+
dbs_set_warnings(dbs_c_api_test)
|
|
168
|
+
add_test(NAME dbs_c_api_test COMMAND dbs_c_api_test)
|
|
169
|
+
|
|
170
|
+
# The documented C example must keep compiling and running.
|
|
171
|
+
add_executable(dbs_example_c_api examples/c_api.c)
|
|
172
|
+
target_link_libraries(dbs_example_c_api PRIVATE dbs)
|
|
173
|
+
dbs_set_warnings(dbs_example_c_api)
|
|
174
|
+
add_test(NAME dbs_example_c_api COMMAND dbs_example_c_api)
|
|
175
|
+
|
|
176
|
+
if(DBS_ENABLE_SANITIZERS)
|
|
177
|
+
# A UBSan-instrumented libdbs needs the sanitizer's C++ runtime, which only
|
|
178
|
+
# the C++ driver links (Clang); plain C consumers are covered by normal builds.
|
|
179
|
+
set_target_properties(dbs_c_api_test dbs_example_c_api PROPERTIES LINKER_LANGUAGE CXX)
|
|
180
|
+
endif()
|
|
181
|
+
|
|
182
|
+
# The CUDA backend source, executed on the CPU and checked against libdbs.
|
|
183
|
+
# Needs POSIX ucontext; Linux is enough to verify the kernel logic.
|
|
184
|
+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
185
|
+
add_executable(dbs_cuda_emulation_tests tests/cuda_emulation_tests.cpp)
|
|
186
|
+
target_include_directories(dbs_cuda_emulation_tests PRIVATE include src tests)
|
|
187
|
+
target_link_libraries(dbs_cuda_emulation_tests PRIVATE dbs)
|
|
188
|
+
dbs_set_fp_model(dbs_cuda_emulation_tests)
|
|
189
|
+
add_test(NAME dbs_cuda_emulation_tests COMMAND dbs_cuda_emulation_tests)
|
|
190
|
+
if(DBS_ENABLE_SANITIZERS)
|
|
191
|
+
# ASan cannot follow ucontext stack switches.
|
|
192
|
+
set_tests_properties(dbs_cuda_emulation_tests PROPERTIES
|
|
193
|
+
ENVIRONMENT "ASAN_OPTIONS=detect_stack_use_after_return=0:detect_leaks=1")
|
|
194
|
+
endif()
|
|
195
|
+
endif()
|
|
196
|
+
|
|
197
|
+
# The native CUDA backend on a real GPU against libdbs, bit for bit. Skipped
|
|
198
|
+
# (exit code 77) when no device is present.
|
|
199
|
+
if(DBS_ENABLE_CUDA)
|
|
200
|
+
find_package(CUDAToolkit REQUIRED)
|
|
201
|
+
add_executable(dbs_cuda_device_tests tests/cuda_device_tests.cpp)
|
|
202
|
+
target_include_directories(dbs_cuda_device_tests PRIVATE tests)
|
|
203
|
+
target_link_libraries(dbs_cuda_device_tests PRIVATE dbs dbs_cuda CUDA::cudart)
|
|
204
|
+
dbs_set_warnings(dbs_cuda_device_tests)
|
|
205
|
+
add_test(NAME dbs_cuda_device_tests COMMAND dbs_cuda_device_tests)
|
|
206
|
+
set_tests_properties(dbs_cuda_device_tests PROPERTIES SKIP_RETURN_CODE 77)
|
|
207
|
+
endif()
|
|
208
|
+
|
|
209
|
+
if(UNIX AND NOT APPLE AND DBS_BUILD_SHARED)
|
|
210
|
+
add_test(NAME dbs_abi_symbols
|
|
211
|
+
COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/check_abi.sh $<TARGET_FILE:dbs>)
|
|
212
|
+
endif()
|
|
213
|
+
endif()
|
|
214
|
+
|
|
215
|
+
if(DBS_BUILD_BENCHMARKS)
|
|
216
|
+
add_executable(dbs_bench benchmarks/dbs_bench.cpp)
|
|
217
|
+
target_link_libraries(dbs_bench PRIVATE dbs)
|
|
218
|
+
endif()
|
|
219
|
+
|
|
220
|
+
if(DBS_BUILD_FUZZER)
|
|
221
|
+
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
222
|
+
message(FATAL_ERROR "DBS_BUILD_FUZZER requires Clang (libFuzzer)")
|
|
223
|
+
endif()
|
|
224
|
+
add_executable(dbs_fuzz tests/fuzz_dbs.cpp)
|
|
225
|
+
target_link_libraries(dbs_fuzz PRIVATE dbs)
|
|
226
|
+
target_compile_options(dbs_fuzz PRIVATE -fsanitize=fuzzer)
|
|
227
|
+
target_link_options(dbs_fuzz PRIVATE -fsanitize=fuzzer)
|
|
228
|
+
endif()
|
|
229
|
+
|
|
230
|
+
# ---------------------------------------------------------------------------
|
|
231
|
+
# Install: headers, libraries, CMake package (find_package(beamgrad)), pkg-config
|
|
232
|
+
# ---------------------------------------------------------------------------
|
|
233
|
+
|
|
234
|
+
install(TARGETS dbs dbs_cuda EXPORT beamgradTargets
|
|
235
|
+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
236
|
+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
237
|
+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
238
|
+
install(FILES include/dbs.h include/dbs_cuda.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
|
239
|
+
install(EXPORT beamgradTargets
|
|
240
|
+
FILE beamgradTargets.cmake
|
|
241
|
+
NAMESPACE beamgrad::
|
|
242
|
+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beamgrad)
|
|
243
|
+
|
|
244
|
+
include(CMakePackageConfigHelpers)
|
|
245
|
+
write_basic_package_version_file(
|
|
246
|
+
"${PROJECT_BINARY_DIR}/beamgradConfigVersion.cmake"
|
|
247
|
+
VERSION ${PROJECT_VERSION}
|
|
248
|
+
COMPATIBILITY SameMajorVersion)
|
|
249
|
+
configure_package_config_file(
|
|
250
|
+
"${PROJECT_SOURCE_DIR}/cmake/beamgradConfig.cmake.in"
|
|
251
|
+
"${PROJECT_BINARY_DIR}/beamgradConfig.cmake"
|
|
252
|
+
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beamgrad)
|
|
253
|
+
install(FILES
|
|
254
|
+
"${PROJECT_BINARY_DIR}/beamgradConfig.cmake"
|
|
255
|
+
"${PROJECT_BINARY_DIR}/beamgradConfigVersion.cmake"
|
|
256
|
+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/beamgrad)
|
|
257
|
+
|
|
258
|
+
configure_file(pkgconfig/dbs.pc.in dbs.pc @ONLY)
|
|
259
|
+
install(FILES "${PROJECT_BINARY_DIR}/dbs.pc" DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
beamgrad-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maged Amr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
include VERSION LICENSE README.md CHANGELOG.md CMakeLists.txt
|
|
2
|
+
recursive-include include *.h
|
|
3
|
+
recursive-include src *.cpp *.hpp
|
|
4
|
+
recursive-include cuda *.cu *.cpp *.hpp
|
|
5
|
+
recursive-include python/csrc *.cpp
|
|
6
|
+
recursive-include cmake *.in *.map
|
|
7
|
+
recursive-include pkgconfig *.in
|
|
8
|
+
recursive-include abi *.symbols
|