fuzzgpu 0.1.8__tar.gz → 0.3.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.
Files changed (68) hide show
  1. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/Cargo.lock +4 -4
  2. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/PKG-INFO +16 -8
  3. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/README.md +15 -7
  4. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/Cargo.toml +1 -1
  5. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/benches/bench.rs +60 -16
  6. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/damerau.rs +604 -160
  7. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/fuzz.rs +385 -32
  8. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/gpu.rs +248 -108
  9. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/jaro.rs +927 -252
  10. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/levenshtein.rs +1456 -445
  11. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/lib.rs +23 -16
  12. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/needleman.rs +734 -193
  13. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/simd.rs +452 -133
  14. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/tests/differential.rs +146 -64
  15. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/tests/kernel_registration.rs +18 -14
  16. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-python/Cargo.toml +2 -2
  17. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-python/src/lib.rs +269 -48
  18. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-wasm/Cargo.toml +1 -1
  19. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/pyproject.toml +1 -1
  20. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_api_signatures.py +20 -7
  21. fuzzgpu-0.3.0/tests/test_gpu_health.py +102 -0
  22. fuzzgpu-0.3.0/tests/test_gpu_threshold_env.py +159 -0
  23. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/Cargo.toml +0 -0
  24. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/LICENSE +0 -0
  25. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/assets/logo.png +0 -0
  26. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/damerau.wgsl +0 -0
  27. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/damerau_matrix.wgsl +0 -0
  28. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/jaro.wgsl +0 -0
  29. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/jaro_matrix.wgsl +0 -0
  30. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/levenshtein.wgsl +0 -0
  31. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/levenshtein_cdist_myers.wgsl +0 -0
  32. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/levenshtein_matrix.wgsl +0 -0
  33. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/levenshtein_myers.wgsl +0 -0
  34. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/levenshtein_short.wgsl +0 -0
  35. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/needleman_affine.wgsl +0 -0
  36. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/src/shaders/needleman_wavefront.wgsl +0 -0
  37. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/tests/differential.proptest-regressions +0 -0
  38. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-core/tests/fixtures/broken.wgsl +0 -0
  39. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-wasm/src/lib.rs +0 -0
  40. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-wasm/tests/differential_harness.js +0 -0
  41. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/crates/fuzzgpu-wasm/tests/js_api.test.cjs +0 -0
  42. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/__init__.py +0 -0
  43. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/__init__.pyi +0 -0
  44. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/DamerauLevenshtein.py +0 -0
  45. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/Hamming.py +0 -0
  46. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/Indel.py +0 -0
  47. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/Jaro.py +0 -0
  48. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/JaroWinkler.py +0 -0
  49. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/LCSseq.py +0 -0
  50. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/Levenshtein.py +0 -0
  51. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/OSA.py +0 -0
  52. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/Postfix.py +0 -0
  53. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/Prefix.py +0 -0
  54. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/__init__.py +0 -0
  55. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/__init__.pyi +0 -0
  56. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/distance/_common.py +0 -0
  57. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/fuzz.py +0 -0
  58. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/fuzz.pyi +0 -0
  59. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/process.py +0 -0
  60. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/python/fuzzgpu/process.pyi +0 -0
  61. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_basic.py +0 -0
  62. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_concurrency.py +0 -0
  63. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_edge_cases.py +0 -0
  64. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_invariants.py +0 -0
  65. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_out_buffers.py +0 -0
  66. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_rapidfuzz_compat.py +0 -0
  67. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/test_stress.py +0 -0
  68. {fuzzgpu-0.1.8 → fuzzgpu-0.3.0}/tests/wasm_python_differential.py +0 -0
@@ -308,9 +308,9 @@ dependencies = [
308
308
 
309
309
  [[package]]
310
310
  name = "either"
311
- version = "1.17.0"
311
+ version = "1.18.0"
312
312
  source = "registry+https://github.com/rust-lang/crates.io-index"
313
- checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
313
+ checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
314
314
 
315
315
  [[package]]
316
316
  name = "equivalent"
@@ -372,7 +372,7 @@ dependencies = [
372
372
 
373
373
  [[package]]
374
374
  name = "fuzzgpu-core"
375
- version = "0.1.8"
375
+ version = "0.3.0"
376
376
  dependencies = [
377
377
  "bytemuck",
378
378
  "criterion",
@@ -386,7 +386,7 @@ dependencies = [
386
386
 
387
387
  [[package]]
388
388
  name = "fuzzgpu-python"
389
- version = "0.1.8"
389
+ version = "0.3.0"
390
390
  dependencies = [
391
391
  "fuzzgpu-core",
392
392
  "log",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fuzzgpu
3
- Version: 0.1.8
3
+ Version: 0.3.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -37,7 +37,8 @@ Project-URL: Repository, https://github.com/kuntal-devrat/fuzzgpu
37
37
 
38
38
  *Cross-platform GPU compute via WebGPU (`wgpu`) & Multi-Core CPU parallelism with Rayon. Zero CUDA dependencies.*
39
39
 
40
- [![PyPI Version](https://img.shields.io/badge/pypi-v0.1.8-blue.svg?style=flat-square)](https://pypi.org/project/fuzzgpu/)
40
+ [![PyPI
41
+ Version](https://img.shields.io/badge/pypi-v0.3.0-blue.svg?style=flat-square)](https://pypi.org/project/fuzzgpu/)
41
42
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg?style=flat-square)](https://opensource.org/licenses/MIT)
42
43
  [![Rust](https://img.shields.io/badge/rust-1.87+-orange.svg?style=flat-square)](https://www.rust-lang.org)
43
44
  [![Cross Platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux%20%7C%20WASM-lightgrey.svg?style=flat-square)](https://github.com/kuntal-devrat/fuzzgpu)
@@ -60,7 +61,7 @@ No NVIDIA CUDA drivers or complex toolkits required.
60
61
 
61
62
  ---
62
63
 
63
- ## What's New in v0.1.8
64
+ ## What's New in v0.3.0
64
65
 
65
66
  ### Production hardening
66
67
  - **Kernel `get()` panics eliminated** — all four GPU kernels (`GpuLevenshteinKernel`,
@@ -163,10 +164,17 @@ The full Python layer is now byte-identical to rapidfuzz 3.14.5 over a 169,744-p
163
164
 
164
165
  ## Benchmark Results
165
166
 
166
- *Hardware: Intel(R) Iris(R) Xe Graphics (Vulkan) + Intel Core i7 (Rayon uses all cores)*
167
- *Versions: fuzzgpu 0.1.8 · rapidfuzz 3.14.5 · python-Levenshtein 0.27.4*
167
+ *Hardware: Intel(R) Iris(R) Xe Graphics — integrated GPU (Vulkan) + Intel Core i7 (Rayon, all cores)*
168
+ *Versions: fuzzgpu 0.3.0 · rapidfuzz 3.14.5 · python-Levenshtein 0.27.4*
168
169
  *Median of 7 runs after warmup. Reproduce: `python benchmarks/bench_compare.py`*
169
170
 
171
+ > **GPU class note:** These numbers are from an **integrated GPU** (iGPU), which shares memory
172
+ > bandwidth with the CPU and has a ~1 ms dispatch round-trip. On a **discrete GPU** (dGPU) the
173
+ > GPU columns improve significantly — expect 3–10× better GPU throughput and GPU routing kicking
174
+ > in at much smaller batch sizes (threshold drops from ~500 pairs to ~64 pairs automatically).
175
+ > Concurrency gains (multiple Python threads, after the wgpu fix ships) add a further 2–4×
176
+ > on top for server workloads regardless of GPU class.
177
+
170
178
  ### Levenshtein Batch (1 query × N candidates, 10-char strings)
171
179
  | Batch Size | `fuzzgpu` (GPU) | `fuzzgpu` (CPU) | `rapidfuzz` | vs RF (GPU) | vs RF (CPU) |
172
180
  | :--- | :---: | :---: | :---: | :---: | :---: |
@@ -222,7 +230,7 @@ pip install fuzzgpu
222
230
  ```toml
223
231
  # Rust
224
232
  [dependencies]
225
- fuzzgpu-core = "0.1.8"
233
+ fuzzgpu-core = "0.3.0"
226
234
  ```
227
235
 
228
236
  ---
@@ -318,7 +326,7 @@ fuzzgpu.set_cpu_only(True) # force CPU-only mode
318
326
 
319
327
  ```toml
320
328
  [dependencies]
321
- fuzzgpu-core = "0.1.8" # GPU + CPU fallback
329
+ fuzzgpu-core = "0.3.0" # GPU + CPU fallback
322
330
  # fuzzgpu-core = { version = "0.1.7", default-features = false } # CPU-only
323
331
  ```
324
332
 
@@ -464,7 +472,7 @@ cargo test --workspace
464
472
  | `FUZZGPU_DEBUG` | Log GPU→CPU fallback decisions |
465
473
  | `FUZZGPU_SIMD` | Force ISA: `portable\|neon\|avx2\|avx512` |
466
474
  | `FUZZGPU_READBACK_TIMEOUT_MS` | GPU readback timeout (default 10000 ms) |
467
- | `FUZZGPU_SKIP_DISPATCH_LOCK` | Bypass serialization lock (repro only) |
475
+ | `FUZZGPU_SKIP_DISPATCH_LOCK` | Opt-in GPU dispatch serialization (safety valve for the rare gfx-rs/wgpu#10085 crash class on Intel D3D12; dispatch is fully concurrent by default) |
468
476
  | `FUZZGPU_REQUIRE_GPU` | In tests: fail instead of skip when no GPU |
469
477
  | `WGPU_BACKEND` | Force wgpu backend: `vulkan\|metal\|dx12` |
470
478
  | `PROPTEST_CASES` | Override proptest case count |
@@ -8,7 +8,8 @@
8
8
 
9
9
  *Cross-platform GPU compute via WebGPU (`wgpu`) & Multi-Core CPU parallelism with Rayon. Zero CUDA dependencies.*
10
10
 
11
- [![PyPI Version](https://img.shields.io/badge/pypi-v0.1.8-blue.svg?style=flat-square)](https://pypi.org/project/fuzzgpu/)
11
+ [![PyPI
12
+ Version](https://img.shields.io/badge/pypi-v0.3.0-blue.svg?style=flat-square)](https://pypi.org/project/fuzzgpu/)
12
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg?style=flat-square)](https://opensource.org/licenses/MIT)
13
14
  [![Rust](https://img.shields.io/badge/rust-1.87+-orange.svg?style=flat-square)](https://www.rust-lang.org)
14
15
  [![Cross Platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux%20%7C%20WASM-lightgrey.svg?style=flat-square)](https://github.com/kuntal-devrat/fuzzgpu)
@@ -31,7 +32,7 @@ No NVIDIA CUDA drivers or complex toolkits required.
31
32
 
32
33
  ---
33
34
 
34
- ## What's New in v0.1.8
35
+ ## What's New in v0.3.0
35
36
 
36
37
  ### Production hardening
37
38
  - **Kernel `get()` panics eliminated** — all four GPU kernels (`GpuLevenshteinKernel`,
@@ -134,10 +135,17 @@ The full Python layer is now byte-identical to rapidfuzz 3.14.5 over a 169,744-p
134
135
 
135
136
  ## Benchmark Results
136
137
 
137
- *Hardware: Intel(R) Iris(R) Xe Graphics (Vulkan) + Intel Core i7 (Rayon uses all cores)*
138
- *Versions: fuzzgpu 0.1.8 · rapidfuzz 3.14.5 · python-Levenshtein 0.27.4*
138
+ *Hardware: Intel(R) Iris(R) Xe Graphics — integrated GPU (Vulkan) + Intel Core i7 (Rayon, all cores)*
139
+ *Versions: fuzzgpu 0.3.0 · rapidfuzz 3.14.5 · python-Levenshtein 0.27.4*
139
140
  *Median of 7 runs after warmup. Reproduce: `python benchmarks/bench_compare.py`*
140
141
 
142
+ > **GPU class note:** These numbers are from an **integrated GPU** (iGPU), which shares memory
143
+ > bandwidth with the CPU and has a ~1 ms dispatch round-trip. On a **discrete GPU** (dGPU) the
144
+ > GPU columns improve significantly — expect 3–10× better GPU throughput and GPU routing kicking
145
+ > in at much smaller batch sizes (threshold drops from ~500 pairs to ~64 pairs automatically).
146
+ > Concurrency gains (multiple Python threads, after the wgpu fix ships) add a further 2–4×
147
+ > on top for server workloads regardless of GPU class.
148
+
141
149
  ### Levenshtein Batch (1 query × N candidates, 10-char strings)
142
150
  | Batch Size | `fuzzgpu` (GPU) | `fuzzgpu` (CPU) | `rapidfuzz` | vs RF (GPU) | vs RF (CPU) |
143
151
  | :--- | :---: | :---: | :---: | :---: | :---: |
@@ -193,7 +201,7 @@ pip install fuzzgpu
193
201
  ```toml
194
202
  # Rust
195
203
  [dependencies]
196
- fuzzgpu-core = "0.1.8"
204
+ fuzzgpu-core = "0.3.0"
197
205
  ```
198
206
 
199
207
  ---
@@ -289,7 +297,7 @@ fuzzgpu.set_cpu_only(True) # force CPU-only mode
289
297
 
290
298
  ```toml
291
299
  [dependencies]
292
- fuzzgpu-core = "0.1.8" # GPU + CPU fallback
300
+ fuzzgpu-core = "0.3.0" # GPU + CPU fallback
293
301
  # fuzzgpu-core = { version = "0.1.7", default-features = false } # CPU-only
294
302
  ```
295
303
 
@@ -435,7 +443,7 @@ cargo test --workspace
435
443
  | `FUZZGPU_DEBUG` | Log GPU→CPU fallback decisions |
436
444
  | `FUZZGPU_SIMD` | Force ISA: `portable\|neon\|avx2\|avx512` |
437
445
  | `FUZZGPU_READBACK_TIMEOUT_MS` | GPU readback timeout (default 10000 ms) |
438
- | `FUZZGPU_SKIP_DISPATCH_LOCK` | Bypass serialization lock (repro only) |
446
+ | `FUZZGPU_SKIP_DISPATCH_LOCK` | Opt-in GPU dispatch serialization (safety valve for the rare gfx-rs/wgpu#10085 crash class on Intel D3D12; dispatch is fully concurrent by default) |
439
447
  | `FUZZGPU_REQUIRE_GPU` | In tests: fail instead of skip when no GPU |
440
448
  | `WGPU_BACKEND` | Force wgpu backend: `vulkan\|metal\|dx12` |
441
449
  | `PROPTEST_CASES` | Override proptest case count |
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "fuzzgpu-core"
3
- version = "0.1.8"
3
+ version = "0.3.0"
4
4
  edition = "2021"
5
5
  description = "GPU-accelerated fuzzy string matching engine"
6
6
  license = "MIT"
@@ -13,7 +13,9 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
13
13
  use fuzzgpu_core::damerau::damerau_levenshtein_batch;
14
14
  use fuzzgpu_core::fuzz::ratio;
15
15
  use fuzzgpu_core::jaro::{jaro_winkler, jaro_winkler_batch};
16
- use fuzzgpu_core::levenshtein::{levenshtein_cdist_cpu, levenshtein_distance_raw, LevenshteinKernel};
16
+ use fuzzgpu_core::levenshtein::{
17
+ levenshtein_cdist_cpu, levenshtein_distance_raw, LevenshteinKernel,
18
+ };
17
19
  use fuzzgpu_core::needleman::{needleman_wunsch_affine, needleman_wunsch_affine_batch};
18
20
  use fuzzgpu_core::simd::levenshtein_myers;
19
21
 
@@ -24,7 +26,9 @@ fn gen_strings(count: usize, len: usize, seed: u64) -> Vec<String> {
24
26
  for _ in 0..count {
25
27
  let mut s = String::with_capacity(len);
26
28
  for _ in 0..len {
27
- state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
29
+ state = state
30
+ .wrapping_mul(6364136223846793005)
31
+ .wrapping_add(1442695040888963407);
28
32
  s.push((b'a' + ((state >> 33) as u8 % 26)) as char);
29
33
  }
30
34
  out.push(s);
@@ -47,7 +51,11 @@ fn cpu_benches(c: &mut Criterion) {
47
51
  let long = gen_strings(2, 256, 3);
48
52
 
49
53
  let mut g = c.benchmark_group("scalar");
50
- for (name, s) in [("short_8", &short), ("medium_64", &medium), ("long_256", &long)] {
54
+ for (name, s) in [
55
+ ("short_8", &short),
56
+ ("medium_64", &medium),
57
+ ("long_256", &long),
58
+ ] {
51
59
  let (s1, s2) = (&s[0], &s[1]);
52
60
  g.bench_function(format!("levenshtein/{name}"), |b| {
53
61
  b.iter(|| black_box(levenshtein_distance_raw(s1, s2)))
@@ -62,7 +70,11 @@ fn cpu_benches(c: &mut Criterion) {
62
70
  b.iter(|| black_box(ratio(s1, s2)))
63
71
  });
64
72
  g.bench_function(format!("needleman_affine/{name}"), |b| {
65
- b.iter(|| black_box(needleman_wunsch_affine(s1, s2, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND)))
73
+ b.iter(|| {
74
+ black_box(needleman_wunsch_affine(
75
+ s1, s2, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND,
76
+ ))
77
+ })
66
78
  });
67
79
  g.bench_function(format!("damerau/{name}"), |b| {
68
80
  b.iter(|| black_box(fuzzgpu_core::damerau::damerau_levenshtein_distance(s1, s2)))
@@ -89,14 +101,27 @@ fn cpu_benches(c: &mut Criterion) {
89
101
  b.iter(|| black_box(jaro_winkler_batch(query, &cand_refs, 0.1)))
90
102
  });
91
103
  g.bench_function("needleman_affine_batch_1000", |b| {
92
- b.iter(|| black_box(needleman_wunsch_affine_batch(query, &cand_refs, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND)))
104
+ b.iter(|| {
105
+ black_box(needleman_wunsch_affine_batch(
106
+ query, &cand_refs, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND,
107
+ ))
108
+ })
93
109
  });
94
110
  // Long-string needleman (80 chars): the anti-diagonal wavefront GPU path's
95
111
  // target workload; Rayon CPU is the comparison baseline.
96
112
  let cands_nw80 = gen_strings(1000, 80, 0xAB);
97
113
  let cand_refs_nw80: Vec<&str> = cands_nw80.iter().map(|s| s.as_str()).collect();
98
114
  g.bench_function("needleman_affine_batch_1000_long80_large", |b| {
99
- b.iter(|| black_box(needleman_wunsch_affine_batch(query, &cand_refs_nw80, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND)))
115
+ b.iter(|| {
116
+ black_box(needleman_wunsch_affine_batch(
117
+ query,
118
+ &cand_refs_nw80,
119
+ MATCH,
120
+ MISMATCH,
121
+ GAP_OPEN,
122
+ GAP_EXTEND,
123
+ ))
124
+ })
100
125
  });
101
126
  g.bench_function("damerau_batch_1000", |b| {
102
127
  b.iter(|| black_box(damerau_levenshtein_batch(query, &cand_refs)))
@@ -128,8 +153,9 @@ fn cpu_benches(c: &mut Criterion) {
128
153
  b.iter(|| black_box(levenshtein_cdist_cpu(&refs_a_1k, &refs_b_1k)))
129
154
  });
130
155
  // Sequential 10 x 1000 pairs: the CPU baseline for the batched-GPU bench.
131
- let cands10: Vec<Vec<String>> =
132
- (0..10).map(|i| gen_strings(1000, 16, 0x100 + i as u64)).collect();
156
+ let cands10: Vec<Vec<String>> = (0..10)
157
+ .map(|i| gen_strings(1000, 16, 0x100 + i as u64))
158
+ .collect();
133
159
  let ops10: Vec<Vec<(&str, &str)>> = cands10.iter().map(|c| make_pairs(query, c)).collect();
134
160
  g.bench_function("levenshtein_10x1000_seq_cpu", |b| {
135
161
  b.iter(|| {
@@ -190,13 +216,23 @@ fn gpu_benches(c: &mut Criterion) {
190
216
  match GpuNeedlemanAffineKernel::get() {
191
217
  Ok(kernel) => {
192
218
  g.bench_function("needleman_affine_batch_1000", |b| {
193
- b.iter(|| black_box(kernel.compute_batch(&pairs, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND)))
219
+ b.iter(|| {
220
+ black_box(kernel.compute_batch(&pairs, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND))
221
+ })
194
222
  });
195
223
  // 80-char pairs: routes to the anti-diagonal wavefront kernel.
196
224
  let cands_nw80 = gen_strings(1000, 80, 0xAB);
197
225
  let pairs_nw80 = make_pairs(query, &cands_nw80);
198
226
  g.bench_function("needleman_affine_batch_1000_long80_large", |b| {
199
- b.iter(|| black_box(kernel.compute_batch(&pairs_nw80, MATCH, MISMATCH, GAP_OPEN, GAP_EXTEND)))
227
+ b.iter(|| {
228
+ black_box(kernel.compute_batch(
229
+ &pairs_nw80,
230
+ MATCH,
231
+ MISMATCH,
232
+ GAP_OPEN,
233
+ GAP_EXTEND,
234
+ ))
235
+ })
200
236
  });
201
237
  }
202
238
  Err(e) => {
@@ -247,9 +283,11 @@ fn gpu_benches(c: &mut Criterion) {
247
283
  });
248
284
  // 10 x 1000 pairs: one batched dispatch+readback vs 10 sequential
249
285
  // sync-round-trips. Same total work as cpu_batch/..._seq_cpu.
250
- let cands10: Vec<Vec<String>> =
251
- (0..10).map(|i| gen_strings(1000, 16, 0x100 + i as u64)).collect();
252
- let ops10: Vec<Vec<(&str, &str)>> = cands10.iter().map(|c| make_pairs(query, c)).collect();
286
+ let cands10: Vec<Vec<String>> = (0..10)
287
+ .map(|i| gen_strings(1000, 16, 0x100 + i as u64))
288
+ .collect();
289
+ let ops10: Vec<Vec<(&str, &str)>> =
290
+ cands10.iter().map(|c| make_pairs(query, c)).collect();
253
291
  g.bench_function("levenshtein_10x1000_seq", |b| {
254
292
  b.iter(|| {
255
293
  for op in &ops10 {
@@ -268,10 +306,16 @@ fn gpu_benches(c: &mut Criterion) {
268
306
  });
269
307
  }
270
308
  Err(e) => {
271
- eprintln!("WARN: no GPU device, skipping large-scale GpuLevenshteinKernel benches: {e}");
309
+ eprintln!(
310
+ "WARN: no GPU device, skipping large-scale GpuLevenshteinKernel benches: {e}"
311
+ );
272
312
  g.bench_function("levenshtein_batch_100k_large", |b| b.iter(|| black_box(0)));
273
- g.bench_function("levenshtein_batch_1000_long256_large", |b| b.iter(|| black_box(0)));
274
- g.bench_function("levenshtein_cdist_1000x1000_large", |b| b.iter(|| black_box(0)));
313
+ g.bench_function("levenshtein_batch_1000_long256_large", |b| {
314
+ b.iter(|| black_box(0))
315
+ });
316
+ g.bench_function("levenshtein_cdist_1000x1000_large", |b| {
317
+ b.iter(|| black_box(0))
318
+ });
275
319
  g.bench_function("levenshtein_10x1000_seq", |b| b.iter(|| black_box(0)));
276
320
  g.bench_function("levenshtein_10x1000_batched", |b| b.iter(|| black_box(0)));
277
321
  }