rns-engine 0.11.2__tar.gz → 0.13.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.
- rns_engine-0.13.0/MANIFEST.in +4 -0
- rns_engine-0.13.0/PKG-INFO +85 -0
- rns_engine-0.13.0/README.md +57 -0
- rns_engine-0.13.0/benchmarks/t4/archive/G4_SERIES1_EVIDENCE.md +170 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/pyproject.toml +7 -6
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/__init__.py +6 -42
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_public_summary.json +8 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_runtime.json +97 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c01.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c02.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c03.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c04.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c05.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c06.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c07.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c08.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c09.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c10.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c11.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/data/g4s1_public_t4_source_c12.b64 +1 -0
- rns_engine-0.13.0/src/rns_engine/g4_integer_benchmark.py +454 -0
- rns_engine-0.13.0/src/rns_engine/g4_matmul.py +145 -0
- rns_engine-0.13.0/src/rns_engine/g4_public.py +243 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/g4_results.py +42 -8
- rns_engine-0.13.0/src/rns_engine/g4_runtime.py +293 -0
- rns_engine-0.13.0/src/rns_engine/g4_xops.py +207 -0
- rns_engine-0.13.0/src/rns_engine.egg-info/PKG-INFO +85 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine.egg-info/SOURCES.txt +30 -16
- rns_engine-0.13.0/tests/test_g4_api_exports.py +8 -0
- rns_engine-0.13.0/tests/test_g4_matmul_api.py +41 -0
- rns_engine-0.13.0/tests/test_g4_public.py +63 -0
- rns_engine-0.13.0/tests/test_g4_results.py +64 -0
- rns_engine-0.13.0/tests/test_g4_runtime.py +24 -0
- rns_engine-0.13.0/tests/test_g4_runtime_metadata.py +21 -0
- rns_engine-0.13.0/tests/test_g4_runtime_payload_parts.py +10 -0
- rns_engine-0.13.0/tests/test_g4_source_privacy.py +22 -0
- rns_engine-0.13.0/tests/test_g4_xops.py +56 -0
- rns_engine-0.13.0/tests/test_g4_xops_key_text.py +12 -0
- rns_engine-0.13.0/tests/test_g4_xops_rational_boundary.py +22 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_packaging.py +2 -2
- rns_engine-0.13.0/tests/test_readme.py +9 -0
- rns_engine-0.11.2/CAPACITY_PLANNING.md +0 -178
- rns_engine-0.11.2/CUDA_PARALLEL_LANES.md +0 -100
- rns_engine-0.11.2/G4_SERIES1_EVIDENCE.md +0 -66
- rns_engine-0.11.2/MANIFEST.in +0 -9
- rns_engine-0.11.2/PKG-INFO +0 -481
- rns_engine-0.11.2/PRE_CUDA_READINESS.md +0 -72
- rns_engine-0.11.2/README.md +0 -455
- rns_engine-0.11.2/benchmarks/weighted_int32_baseline.py +0 -423
- rns_engine-0.11.2/colab/T4_EXACT_GEMM_BRINGUP.ipynb +0 -152
- rns_engine-0.11.2/src/rns_engine/cuda_contract.py +0 -281
- rns_engine-0.11.2/src/rns_engine/lane_plan.py +0 -66
- rns_engine-0.11.2/src/rns_engine/pre_cuda.py +0 -221
- rns_engine-0.11.2/src/rns_engine/rail_planning.py +0 -318
- rns_engine-0.11.2/src/rns_engine.egg-info/PKG-INFO +0 -481
- rns_engine-0.11.2/src/rns_engine.egg-info/entry_points.txt +0 -2
- rns_engine-0.11.2/tests/test_cuda_contract.py +0 -56
- rns_engine-0.11.2/tests/test_g4_results.py +0 -46
- rns_engine-0.11.2/tests/test_pre_cuda.py +0 -45
- rns_engine-0.11.2/tests/test_pre_cuda_assets.py +0 -30
- rns_engine-0.11.2/tests/test_rail_planning.py +0 -170
- rns_engine-0.11.2/tests/test_weighted_benchmark.py +0 -71
- {rns_engine-0.11.2 → rns_engine-0.13.0}/LICENSE +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/setup.cfg +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/setup.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/_core.cpp +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/_weighted.cpp +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/capacity.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/coefficients.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part01.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part02.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part03.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part04.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part05.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part06a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part06b.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part07.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part08a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part08b.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part09.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part10a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part10b1.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part10b2.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part10b4.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part11.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part12a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part12b.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part13.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part14a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part14b.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part15a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part15b.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part16a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part16b.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part17a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part17b1.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part17b2a.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part17b2b1.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part17b2b2.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_replay.part17b2b3.b64 +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/data/g4s1_t4_runtime.json +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/engine.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/exact_gemm.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/g4_benchmark.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/g4_trust.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/signed.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/weighted.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine/wide.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine.egg-info/dependency_links.txt +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine.egg-info/not-zip-safe +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine.egg-info/requires.txt +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/src/rns_engine.egg-info/top_level.txt +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_capacity.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_coefficients.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_exact_gemm.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_g4_benchmark.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_g4_species_labels.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_g4_trust.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_rns.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_session.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_signed.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_weighted.py +0 -0
- {rns_engine-0.11.2 → rns_engine-0.13.0}/tests/test_wide.py +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rns_engine
|
|
3
|
+
Version: 0.13.0
|
|
4
|
+
Summary: Exact modular arithmetic and matrix multiplication over integers and rationals.
|
|
5
|
+
Author: Evan Wesley
|
|
6
|
+
License-Expression: AGPL-3.0-only
|
|
7
|
+
Project-URL: Repository, https://github.com/playfularchitect/rns_engine
|
|
8
|
+
Project-URL: Benchmarks, https://github.com/playfularchitect/rns_engine/tree/main/benchmarks
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Programming Language :: C++
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Requires-Python: <3.15,>=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: numpy>=1.23
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Requires-Dist: pytest; extra == "test"
|
|
24
|
+
Requires-Dist: tomli>=1; python_version < "3.11" and extra == "test"
|
|
25
|
+
Requires-Dist: numpy==2.2.6; python_version < "3.14" and extra == "test"
|
|
26
|
+
Requires-Dist: numpy==2.4.5; python_version >= "3.14" and extra == "test"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# RNS Engine
|
|
30
|
+
|
|
31
|
+
RNS Engine is a Python library for exact arithmetic with a native C++ core. It began as an AVX2 CPU engine for modular integer arithmetic and now includes exact integer and shared-scale rational matrix multiplication.
|
|
32
|
+
|
|
33
|
+
## Install and run
|
|
34
|
+
|
|
35
|
+
Use Python 3.10–3.14. The CPU engine runs without a GPU. The x86-64 builds require AVX2. [PyPI package](https://pypi.org/project/rns-engine/)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python -m pip install rns_engine
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Compute 1,000 exact updates of `x ← (1_000_003 × x + 7) mod M` per input and check the result against Python integers.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import numpy as np
|
|
45
|
+
import rns_engine as rns
|
|
46
|
+
|
|
47
|
+
values = np.array([1, 5, 123_456_789], dtype=np.uint64)
|
|
48
|
+
result = rns.affine_repeat_u64_io(values, 1_000_003, 7, 1_000)
|
|
49
|
+
|
|
50
|
+
reference = [int(value) for value in values]
|
|
51
|
+
for _ in range(1_000):
|
|
52
|
+
reference = [(1_000_003 * value + 7) % rns.M for value in reference]
|
|
53
|
+
|
|
54
|
+
assert result.tolist() == reference
|
|
55
|
+
print(result.tolist())
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Original CPU engine
|
|
59
|
+
|
|
60
|
+
The engine encodes integers as residues modulo **127, 8,191, 65,536, and 524,287**. It performs arithmetic on those residues and reconstructs the result with Garner-style Chinese remainder reconstruction. The base engine works modulo **35,742,890,181,197,824**.
|
|
61
|
+
|
|
62
|
+
In the original **two-core Google Colab CPU benchmark**, AVX2 and two OpenMP threads averaged **108.92 billion equivalent exact modular multiply-add steps per second**, with a best run of **112.07 billion**. The workload applied 1,000 repeated updates to one million inputs. The engine composes the updates into one exact transformation per input, so the rate counts the logical steps that transformation represents.
|
|
63
|
+
|
|
64
|
+
[Original Colab notebook](https://colab.research.google.com/drive/18RIQSLf4Vf5xUnwEmDwYNPJDLSM_Stqa?usp=sharing) · [Original source (v0.4.1)](https://github.com/playfularchitect/rns_engine/tree/v0.4.1) · [CPU benchmark details](https://github.com/playfularchitect/rns_engine/tree/main/benchmarks/cpu)
|
|
65
|
+
|
|
66
|
+
## Exact matrix multiplication on NVIDIA Tesla T4
|
|
67
|
+
|
|
68
|
+
The published benchmark compared RNS Engine's exact matrix multiplication (GEMM) with NVIDIA **cuBLASLt FP16-input GEMM** across 1,024 shapes on a Tesla T4.
|
|
69
|
+
|
|
70
|
+
| Exact workload | Wins | Losses | Ties | Errors | Geometric mean speedup |
|
|
71
|
+
| --- | ---: | ---: | ---: | ---: | --- |
|
|
72
|
+
| Signed INT8 inputs, INT32 output | **938** | 86 | 0 | 0 | **1.235×** across all shapes |
|
|
73
|
+
| Shared-scale rational inputs | **870** | 110 | 41 | 3 | **1.417×** across wins |
|
|
74
|
+
|
|
75
|
+
Shared-scale rational matrices use one common denominator per matrix. The integer benchmark timed GPU-resident computation. The rational benchmark also included the bookkeeping needed to return the exact rational result. Python call overhead and host–device transfers are outside the comparison.
|
|
76
|
+
|
|
77
|
+
[T4 benchmark methodology and evidence](https://github.com/playfularchitect/rns_engine/tree/main/benchmarks/t4)
|
|
78
|
+
|
|
79
|
+
## Repository
|
|
80
|
+
|
|
81
|
+
- [Source](https://github.com/playfularchitect/rns_engine/tree/main/src/rns_engine) contains the native CPU core, Python API, and matrix multiplication implementations.
|
|
82
|
+
- [Benchmarks](https://github.com/playfularchitect/rns_engine/tree/main/benchmarks) contains CPU reproduction material and the frozen Tesla T4 evidence.
|
|
83
|
+
- [Tests](https://github.com/playfularchitect/rns_engine/tree/main/tests) covers arithmetic, exactness, and packaging.
|
|
84
|
+
|
|
85
|
+
Licensed under [AGPL-3.0-only](https://github.com/playfularchitect/rns_engine/blob/main/LICENSE).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# RNS Engine
|
|
2
|
+
|
|
3
|
+
RNS Engine is a Python library for exact arithmetic with a native C++ core. It began as an AVX2 CPU engine for modular integer arithmetic and now includes exact integer and shared-scale rational matrix multiplication.
|
|
4
|
+
|
|
5
|
+
## Install and run
|
|
6
|
+
|
|
7
|
+
Use Python 3.10–3.14. The CPU engine runs without a GPU. The x86-64 builds require AVX2. [PyPI package](https://pypi.org/project/rns-engine/)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
python -m pip install rns_engine
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Compute 1,000 exact updates of `x ← (1_000_003 × x + 7) mod M` per input and check the result against Python integers.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import numpy as np
|
|
17
|
+
import rns_engine as rns
|
|
18
|
+
|
|
19
|
+
values = np.array([1, 5, 123_456_789], dtype=np.uint64)
|
|
20
|
+
result = rns.affine_repeat_u64_io(values, 1_000_003, 7, 1_000)
|
|
21
|
+
|
|
22
|
+
reference = [int(value) for value in values]
|
|
23
|
+
for _ in range(1_000):
|
|
24
|
+
reference = [(1_000_003 * value + 7) % rns.M for value in reference]
|
|
25
|
+
|
|
26
|
+
assert result.tolist() == reference
|
|
27
|
+
print(result.tolist())
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Original CPU engine
|
|
31
|
+
|
|
32
|
+
The engine encodes integers as residues modulo **127, 8,191, 65,536, and 524,287**. It performs arithmetic on those residues and reconstructs the result with Garner-style Chinese remainder reconstruction. The base engine works modulo **35,742,890,181,197,824**.
|
|
33
|
+
|
|
34
|
+
In the original **two-core Google Colab CPU benchmark**, AVX2 and two OpenMP threads averaged **108.92 billion equivalent exact modular multiply-add steps per second**, with a best run of **112.07 billion**. The workload applied 1,000 repeated updates to one million inputs. The engine composes the updates into one exact transformation per input, so the rate counts the logical steps that transformation represents.
|
|
35
|
+
|
|
36
|
+
[Original Colab notebook](https://colab.research.google.com/drive/18RIQSLf4Vf5xUnwEmDwYNPJDLSM_Stqa?usp=sharing) · [Original source (v0.4.1)](https://github.com/playfularchitect/rns_engine/tree/v0.4.1) · [CPU benchmark details](https://github.com/playfularchitect/rns_engine/tree/main/benchmarks/cpu)
|
|
37
|
+
|
|
38
|
+
## Exact matrix multiplication on NVIDIA Tesla T4
|
|
39
|
+
|
|
40
|
+
The published benchmark compared RNS Engine's exact matrix multiplication (GEMM) with NVIDIA **cuBLASLt FP16-input GEMM** across 1,024 shapes on a Tesla T4.
|
|
41
|
+
|
|
42
|
+
| Exact workload | Wins | Losses | Ties | Errors | Geometric mean speedup |
|
|
43
|
+
| --- | ---: | ---: | ---: | ---: | --- |
|
|
44
|
+
| Signed INT8 inputs, INT32 output | **938** | 86 | 0 | 0 | **1.235×** across all shapes |
|
|
45
|
+
| Shared-scale rational inputs | **870** | 110 | 41 | 3 | **1.417×** across wins |
|
|
46
|
+
|
|
47
|
+
Shared-scale rational matrices use one common denominator per matrix. The integer benchmark timed GPU-resident computation. The rational benchmark also included the bookkeeping needed to return the exact rational result. Python call overhead and host–device transfers are outside the comparison.
|
|
48
|
+
|
|
49
|
+
[T4 benchmark methodology and evidence](https://github.com/playfularchitect/rns_engine/tree/main/benchmarks/t4)
|
|
50
|
+
|
|
51
|
+
## Repository
|
|
52
|
+
|
|
53
|
+
- [Source](https://github.com/playfularchitect/rns_engine/tree/main/src/rns_engine) contains the native CPU core, Python API, and matrix multiplication implementations.
|
|
54
|
+
- [Benchmarks](https://github.com/playfularchitect/rns_engine/tree/main/benchmarks) contains CPU reproduction material and the frozen Tesla T4 evidence.
|
|
55
|
+
- [Tests](https://github.com/playfularchitect/rns_engine/tree/main/tests) covers arithmetic, exactness, and packaging.
|
|
56
|
+
|
|
57
|
+
Licensed under [AGPL-3.0-only](https://github.com/playfularchitect/rns_engine/blob/main/LICENSE).
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# G4 Series 1 — Frozen Tesla T4 Evidence
|
|
2
|
+
|
|
3
|
+
G4 Series 1 is frozen. This public layer exposes the frozen headline benchmark evidence plus replay-only Tesla T4 runtimes.
|
|
4
|
+
|
|
5
|
+
Speedup ratios in this document are **NVIDIA time / G4 time**, so values above `1.0x` mean G4 is faster.
|
|
6
|
+
|
|
7
|
+
## Two separate frozen claims
|
|
8
|
+
|
|
9
|
+
### Exact integer clean sweep
|
|
10
|
+
|
|
11
|
+
On the frozen `T4GL-1024-v1` suite, the final decision record contains:
|
|
12
|
+
|
|
13
|
+
- 1,024 declared GEMM shapes
|
|
14
|
+
- 938 exact integer G4 wins
|
|
15
|
+
- 86 NVIDIA floating wins
|
|
16
|
+
- 0 statistical ties
|
|
17
|
+
- 0 errors
|
|
18
|
+
- 91.60% G4-win coverage
|
|
19
|
+
- exact replay passed before and after timing on all 1,024 shapes
|
|
20
|
+
- Tesla T4, compute capability 7.5
|
|
21
|
+
- resident-data GEMM kernel benchmark
|
|
22
|
+
|
|
23
|
+
Aggregate speed over **all 1,024 frozen shapes**, including NVIDIA-winning shapes:
|
|
24
|
+
|
|
25
|
+
- geometric mean: **1.235383x**
|
|
26
|
+
- median: **1.256704x**
|
|
27
|
+
|
|
28
|
+
Among the 938 G4-winning shapes:
|
|
29
|
+
|
|
30
|
+
- geometric mean: **1.311052x**
|
|
31
|
+
- median: **1.289235x**
|
|
32
|
+
- best frozen G4 win: **2.647061x**
|
|
33
|
+
|
|
34
|
+
Across the 86 NVIDIA-winning shapes, G4 retained **64.5959% of NVIDIA throughput on geometric average**. Equivalently, the execution-time ratio implied by that geometric mean is a **54.8086% G4 time penalty** on those losses.
|
|
35
|
+
|
|
36
|
+
That loss-side figure is exactly derivable from the frozen aggregate record because the suite contains only 938 G4 wins + 86 NVIDIA wins = 1,024 shapes with no ties/errors:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
all_shape_geomean^1024
|
|
40
|
+
= g4_win_geomean^938 * nvidia_win_ratio_geomean^86
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The floating landscape uses FP16-input cuBLASLt configurations; the retained accumulation mode may be FP16 or FP32 for a given shape. FP16 is the **speed baseline**, not the exactness baseline. Series 1 asks whether exact arithmetic can reach floating-point-class throughput; it does not claim to beat every possible NVIDIA integer GEMM configuration.
|
|
44
|
+
|
|
45
|
+
#### Signed-INT32 range contract
|
|
46
|
+
|
|
47
|
+
The frozen shape manifest has `K <= 4096`. For full-range signed-INT8 inputs, the largest possible product magnitude is `128 × 128 = 16,384`, so the conservative worst-case dot-product magnitude is:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
4096 × 128 × 128 = 67,108,864
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That is safely inside signed INT32 range. Thus all 1,024 certified Series 1 shapes are safe for full-range signed-INT8 inputs under the published exact signed-INT32 output contract.
|
|
54
|
+
|
|
55
|
+
The historical integer archive preserves its actual measurement depth rather than pretending every shape used one block count:
|
|
56
|
+
|
|
57
|
+
- 827 shapes used 21 paired timing blocks
|
|
58
|
+
- 190 shapes used 31 paired timing blocks
|
|
59
|
+
- 7 shapes used 127 paired timing blocks
|
|
60
|
+
|
|
61
|
+
The current public integer replay uses a uniform 31-paired-block classification rule with 20,000 bootstrap resamples, a 95% confidence interval, a 1.002 promotion threshold, and at least 20 / 31 G4 block wins. Runtime or exactness failures fail closed.
|
|
62
|
+
|
|
63
|
+
### Dynamic exact-rational campaign
|
|
64
|
+
|
|
65
|
+
The separately frozen G416 campaign records:
|
|
66
|
+
|
|
67
|
+
- 1,024 evaluated shapes
|
|
68
|
+
- 870 certified exact-rational G4 wins
|
|
69
|
+
- 110 NVIDIA wins
|
|
70
|
+
- 41 statistical ties
|
|
71
|
+
- 3 final errors
|
|
72
|
+
- 84.96% certified exact-rational G4-win coverage
|
|
73
|
+
- 31 paired timing blocks for every certified winner
|
|
74
|
+
- actual non-integer inputs for every certified winner
|
|
75
|
+
- range proof passed for every certified winner
|
|
76
|
+
- FP16 value-set proof passed for every certified winner
|
|
77
|
+
|
|
78
|
+
Among the 870 certified G4-winning shapes:
|
|
79
|
+
|
|
80
|
+
- geometric mean: **1.417436x**
|
|
81
|
+
- median: **1.406441x**
|
|
82
|
+
- best certified G4 win: **2.978048x**
|
|
83
|
+
- slowest certified G4 win: **1.004345x**
|
|
84
|
+
|
|
85
|
+
The frozen public rational summary does **not** expose an all-1,024 speedup aggregate or a loss-side aggregate, so this document does not invent either one.
|
|
86
|
+
|
|
87
|
+
#### What the three final rational errors were
|
|
88
|
+
|
|
89
|
+
The three shapes left in final `ERROR` state were:
|
|
90
|
+
|
|
91
|
+
- `T4GL0140`
|
|
92
|
+
- `T4GL0879`
|
|
93
|
+
- `T4GL1020`
|
|
94
|
+
|
|
95
|
+
Each final row records the same post-measurement bookkeeping exception: `KeyError: 'forecast_debt_bits'`. These were not silent arithmetic mismatches. Each row had already produced 31 paired timings, used actual non-integer inputs, and recorded `range_proved=True` plus `fp16_value_set_proved=True`. The campaign conservatively retained them as `ERROR` rather than reclassifying them from partial evidence.
|
|
96
|
+
|
|
97
|
+
#### Shared-scale rational representation
|
|
98
|
+
|
|
99
|
+
`SharedScaleMatrix` represents one integer numerator matrix divided by one positive integer scale. In the public Series 1 API:
|
|
100
|
+
|
|
101
|
+
- numerator matrices must fit the signed-INT8 fast-input contract;
|
|
102
|
+
- scales are positive Python integers, so scale metadata is not limited by a fixed-width integer type;
|
|
103
|
+
- the output scale is exactly `left.scale * right.scale`;
|
|
104
|
+
- `reduce=True` optionally divides a common factor from the numerator matrix and scale;
|
|
105
|
+
- arbitrary per-element denominators are not part of the Series 1 fast-path contract.
|
|
106
|
+
|
|
107
|
+
**Do not conflate the two percentages.** `938/1024` is the frozen exact-integer clean-sweep result. `870/1024` is the separately certified dynamic exact-rational result.
|
|
108
|
+
|
|
109
|
+
## Benchmark timing boundary vs user-API wall time
|
|
110
|
+
|
|
111
|
+
The frozen **integer** headline is a resident-data GEMM kernel benchmark: GPU data movement, Python-call overhead, and one-shot CPU-array wrapper/runtime work are outside that timing boundary.
|
|
112
|
+
|
|
113
|
+
The frozen **rational** benchmark has its own documented exact-result timing boundary and includes the rational metadata/bookkeeping required to produce the exact rational result. It still is not a one-shot CPU-NumPy `g4_matmul()` wall-time claim.
|
|
114
|
+
|
|
115
|
+
The public `g4_matmul()` API has a different boundary. It accepts CPU NumPy arrays (or `SharedScaleMatrix` objects backed by CPU arrays) and returns a CPU NumPy-backed result. End-to-end `g4_matmul()` wall time therefore includes data movement and wrapper/runtime work that the resident-data integer benchmark excludes.
|
|
116
|
+
|
|
117
|
+
A benchmark that times PyTorch only after tensors are already resident on the GPU must be compared against the same resident-data boundary on the G4 side. Comparing that PyTorch kernel time directly with CPU→CPU `g4_matmul()` wall time mixes two different measurements.
|
|
118
|
+
|
|
119
|
+
Series 1 does **not** claim that one-shot CPU-NumPy→CPU-NumPy `g4_matmul()` wall time beats a pre-resident PyTorch GPU GEMM call.
|
|
120
|
+
|
|
121
|
+
## Python API
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import rns_engine as rns
|
|
125
|
+
|
|
126
|
+
# Frozen evidence; no GPU required.
|
|
127
|
+
rns.g4_results()
|
|
128
|
+
rns.g4_results("integer")
|
|
129
|
+
rns.g4_results("rational")
|
|
130
|
+
|
|
131
|
+
# Tesla T4 only: physical replay of frozen implementations.
|
|
132
|
+
rns.g4_benchmark("quick")
|
|
133
|
+
rns.g4_benchmark("standard")
|
|
134
|
+
rns.g4_benchmark("full")
|
|
135
|
+
|
|
136
|
+
# Or run either species independently.
|
|
137
|
+
rns.g4_integer_benchmark("full")
|
|
138
|
+
rns.g4_rational_benchmark("full")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`g4_results()` reports the frozen scorecards above.
|
|
142
|
+
|
|
143
|
+
`g4_benchmark()` is a convenience runner that physically replays **both** public Series 1 benchmarks on a Tesla T4: G4 INTEGERS first, then G4 RATIONALS. The scores remain separate and no combined win percentage is reported. It does not run G4 search.
|
|
144
|
+
|
|
145
|
+
`g4_integer_benchmark()` and `g4_rational_benchmark()` replay either benchmark independently.
|
|
146
|
+
|
|
147
|
+
## Replay-config provenance boundary
|
|
148
|
+
|
|
149
|
+
Most full rational configs are preserved directly by the frozen work artifacts. Where the frozen result row retained the winner identity but omitted physical fields such as padding or stage ID, the one-time private build enumerated every full frozen candidate matching that retained identity. The public replay selects only within that identity class before measurement and does not claim which omitted member was historical. No timing-based historical config guess is permitted.
|
|
150
|
+
|
|
151
|
+
For floating cuBLASLt baselines, Series 1 originally retained the opaque algorithm object returned by `cublasLtMatmulAlgoGetHeuristic`. The public replay therefore re-queries that same heuristic API on the frozen T4 descriptor/padding context and accepts only returned algorithms whose visible identity and workspace match the archived option. It does not attempt to reconstruct NVIDIA's opaque algorithm object from visible fields with `cublasLtMatmulAlgoInit`.
|
|
152
|
+
|
|
153
|
+
The resulting provenance counts are stored in the packaged runtime metadata and included in benchmark output.
|
|
154
|
+
|
|
155
|
+
## Packaged public evidence/runtime
|
|
156
|
+
|
|
157
|
+
The public package contains:
|
|
158
|
+
|
|
159
|
+
- `g4s1_public_summary.json` — the two frozen headline claims, full scorecard fields available from the archive, and provenance metadata.
|
|
160
|
+
- `g4s1_public_t4_runtime.json` — integer/runtime integrity, hardware boundary, source-family metadata, shape manifest, compile contract, and public-source hashes.
|
|
161
|
+
- rational replay runtime metadata and payload chunks used by the frozen rational replay path.
|
|
162
|
+
- public execution sources required for the Series 1 integer and `g4_matmul()` paths.
|
|
163
|
+
|
|
164
|
+
Every packaged execution/runtime component is SHA-256 integrity checked before use. If the packaged hashes do not match, the public path refuses to run.
|
|
165
|
+
|
|
166
|
+
The detailed G4 search machinery is not needed to reproduce the public replay result. The public package contains the frozen evidence and runtime required by `g4_results()`, `g4_benchmark()`, and the certified Series 1 `g4_matmul()` path.
|
|
167
|
+
|
|
168
|
+
## Claim boundary
|
|
169
|
+
|
|
170
|
+
Series 1 claims only the frozen Tesla T4 / compute capability 7.5 contract documented above. Results on another GPU are a different experiment. Future G4 generations are kept as separate Series rather than rewriting Series 1 evidence.
|
|
@@ -11,8 +11,8 @@ build-backend = "setuptools.build_meta"
|
|
|
11
11
|
|
|
12
12
|
[project]
|
|
13
13
|
name = "rns_engine"
|
|
14
|
-
version = "0.
|
|
15
|
-
description = "Exact
|
|
14
|
+
version = "0.13.0"
|
|
15
|
+
description = "Exact modular arithmetic and matrix multiplication over integers and rationals."
|
|
16
16
|
readme = "README.md"
|
|
17
17
|
requires-python = ">=3.10,<3.15"
|
|
18
18
|
authors = [
|
|
@@ -33,6 +33,10 @@ classifiers = [
|
|
|
33
33
|
"Operating System :: OS Independent",
|
|
34
34
|
]
|
|
35
35
|
|
|
36
|
+
[project.urls]
|
|
37
|
+
Repository = "https://github.com/playfularchitect/rns_engine"
|
|
38
|
+
Benchmarks = "https://github.com/playfularchitect/rns_engine/tree/main/benchmarks"
|
|
39
|
+
|
|
36
40
|
[project.optional-dependencies]
|
|
37
41
|
test = [
|
|
38
42
|
"pytest",
|
|
@@ -41,9 +45,6 @@ test = [
|
|
|
41
45
|
"numpy==2.4.5; python_version >= '3.14'",
|
|
42
46
|
]
|
|
43
47
|
|
|
44
|
-
[project.scripts]
|
|
45
|
-
rns-pre-cuda = "rns_engine.pre_cuda:main"
|
|
46
|
-
|
|
47
48
|
[tool.setuptools]
|
|
48
49
|
package-dir = {"" = "src"}
|
|
49
50
|
include-package-data = true
|
|
@@ -74,4 +75,4 @@ archs = ["x86_64"]
|
|
|
74
75
|
environment = {PIP_ONLY_BINARY = "numpy"}
|
|
75
76
|
|
|
76
77
|
[tool.cibuildwheel.windows]
|
|
77
|
-
archs = ["AMD64"]
|
|
78
|
+
archs = ["AMD64"]
|
|
@@ -68,13 +68,6 @@ from .coefficients import (
|
|
|
68
68
|
GroupedCoefficientCapacityPlan,
|
|
69
69
|
plan_grouped_coefficient_capacity,
|
|
70
70
|
)
|
|
71
|
-
from .rail_planning import (
|
|
72
|
-
MersenneRailCandidate,
|
|
73
|
-
MersenneRailSearchResult,
|
|
74
|
-
MersenneRailSetPlan,
|
|
75
|
-
search_mersenne_rail_sets,
|
|
76
|
-
search_mersenne_rails_for_capacity,
|
|
77
|
-
)
|
|
78
71
|
from .wide import (
|
|
79
72
|
BALANCED_EXTRA_EXPONENTS,
|
|
80
73
|
BASE_MODULI,
|
|
@@ -95,28 +88,9 @@ from .exact_gemm import (
|
|
|
95
88
|
reconstruct_grouped_partials,
|
|
96
89
|
reconstruct_signed_radix,
|
|
97
90
|
)
|
|
98
|
-
from .cuda_contract import (
|
|
99
|
-
BackendVerification,
|
|
100
|
-
CpuExactPipelineBackend,
|
|
101
|
-
CpuGroupedPartialsBackend,
|
|
102
|
-
CudaGemmFixture,
|
|
103
|
-
ExactPipelineBackend,
|
|
104
|
-
build_cuda_gemm_fixture,
|
|
105
|
-
verify_backend,
|
|
106
|
-
)
|
|
107
|
-
from .lane_plan import (
|
|
108
|
-
ParallelRailPrior,
|
|
109
|
-
RailLearningLane,
|
|
110
|
-
build_parallel_rail_prior,
|
|
111
|
-
)
|
|
112
|
-
from .pre_cuda import (
|
|
113
|
-
PreCudaReadinessReport,
|
|
114
|
-
build_default_pre_cuda_fixture,
|
|
115
|
-
default_pre_cuda_matrices,
|
|
116
|
-
run_pre_cuda_readiness,
|
|
117
|
-
)
|
|
118
91
|
from .g4_results import g4_results
|
|
119
|
-
from .
|
|
92
|
+
from .g4_public import g4_benchmark, g4_integer_benchmark, g4_rational_benchmark
|
|
93
|
+
from .g4_matmul import g4_matmul
|
|
120
94
|
|
|
121
95
|
|
|
122
96
|
try:
|
|
@@ -148,8 +122,6 @@ __all__ = [
|
|
|
148
122
|
"GroupedCoefficientCapacityPlan",
|
|
149
123
|
"plan_signed_capacity", "plan_weighted_sum_capacity",
|
|
150
124
|
"plan_digit_plane_gemm_capacity", "plan_grouped_coefficient_capacity",
|
|
151
|
-
"MersenneRailCandidate", "MersenneRailSetPlan", "MersenneRailSearchResult",
|
|
152
|
-
"search_mersenne_rail_sets", "search_mersenne_rails_for_capacity",
|
|
153
125
|
"BASE_MODULI", "SMALLEST_PRODUCT_EXTRA_EXPONENTS",
|
|
154
126
|
"BALANCED_EXTRA_EXPONENTS", "WideRNSConfig", "WideWeightedResult",
|
|
155
127
|
"mersenne_modulus", "moduli_from_mersenne_exponents",
|
|
@@ -158,13 +130,7 @@ __all__ = [
|
|
|
158
130
|
"exact_integer_matmul", "decompose_signed_radix",
|
|
159
131
|
"reconstruct_signed_radix", "grouped_plane_gemm",
|
|
160
132
|
"reconstruct_grouped_partials", "exact_shared_scale_gemm",
|
|
161
|
-
"
|
|
162
|
-
"CpuExactPipelineBackend", "CpuGroupedPartialsBackend",
|
|
163
|
-
"build_cuda_gemm_fixture", "verify_backend",
|
|
164
|
-
"RailLearningLane", "ParallelRailPrior", "build_parallel_rail_prior",
|
|
165
|
-
"PreCudaReadinessReport", "default_pre_cuda_matrices",
|
|
166
|
-
"build_default_pre_cuda_fixture", "run_pre_cuda_readiness",
|
|
167
|
-
"g4_results", "g4_benchmark",
|
|
133
|
+
"g4_results", "g4_benchmark", "g4_integer_benchmark", "g4_rational_benchmark", "g4_matmul",
|
|
168
134
|
"info",
|
|
169
135
|
]
|
|
170
136
|
|
|
@@ -176,8 +142,6 @@ def info():
|
|
|
176
142
|
print(f" Unique bound : |x| < {HALF_M:,}")
|
|
177
143
|
print(f" Moduli : {M0} x {M1} x {M2} x {M3}")
|
|
178
144
|
print(f" AVX2 : {'yes' if HAS_AVX2 else 'no'}")
|
|
179
|
-
print("
|
|
180
|
-
print("
|
|
181
|
-
print("
|
|
182
|
-
print(" Pre-CUDA APIs : seven-rail oracle + exact shared-scale GEMM fixtures")
|
|
183
|
-
print(" G4 APIs : frozen Series 1 evidence + Tesla T4 reproduction benchmark")
|
|
145
|
+
print(" G4 APIs : combined/integer/rational T4 replay + certified exact g4_matmul")
|
|
146
|
+
print(" Exact tools : signed certificates + exact integer/shared-scale reference GEMM")
|
|
147
|
+
print(" Core APIs : encode/decode + add/sub/mul/fma + Session/SignedSession")
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"certified_speedup_geometric_mean": 1.417436071329068,
|
|
15
15
|
"certified_speedup_median": 1.4064410325,
|
|
16
16
|
"compute_capability": "7.5",
|
|
17
|
+
"errors": 3,
|
|
17
18
|
"evaluated_shapes": 1024,
|
|
18
19
|
"final_unresolved_decisions": {
|
|
19
20
|
"ERROR": 3,
|
|
@@ -21,8 +22,10 @@
|
|
|
21
22
|
"STATISTICAL_TIE": 41
|
|
22
23
|
},
|
|
23
24
|
"hardware": "Tesla T4",
|
|
25
|
+
"nvidia_wins": 110,
|
|
24
26
|
"remaining_unresolved": 154,
|
|
25
27
|
"slowest_certified_speedup": 1.004344702,
|
|
28
|
+
"statistical_ties": 41,
|
|
26
29
|
"target_shapes": 1024
|
|
27
30
|
},
|
|
28
31
|
"integer_fp16_input_clean_sweep": {
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
"best_exact_win_speedup": 2.64706111,
|
|
32
35
|
"compute_capability": "7.5",
|
|
33
36
|
"declared_shapes": 1024,
|
|
37
|
+
"errors": 0,
|
|
34
38
|
"exact_win_rate": 0.916015625,
|
|
35
39
|
"exact_win_speedup_geometric_mean": 1.311051665330303,
|
|
36
40
|
"exact_win_speedup_median": 1.289234996,
|
|
@@ -38,6 +42,9 @@
|
|
|
38
42
|
"floating_baseline": "NVIDIA FP16-input cuBLASLt configuration landscape; accumulation mode may be FP16 or FP32 per retained configuration",
|
|
39
43
|
"floating_wins": 86,
|
|
40
44
|
"hardware": "Tesla T4",
|
|
45
|
+
"nvidia_win_g4_execution_time_penalty_from_geomean": 0.5480858262741786,
|
|
46
|
+
"nvidia_win_g4_throughput_retained_geometric_mean": 0.6459590179226226,
|
|
47
|
+
"nvidia_win_loss_metric_derivation": "Derived exactly from the frozen all-shape geometric mean, frozen G4-win geometric mean, and the 938 G4 wins + 86 NVIDIA wins = 1024 shapes with no ties/errors.",
|
|
41
48
|
"overall_speedup_geometric_mean": 1.235383405277301,
|
|
42
49
|
"overall_speedup_median": 1.256704092,
|
|
43
50
|
"paired_block_counts": {
|
|
@@ -45,6 +52,7 @@
|
|
|
45
52
|
"21": 827,
|
|
46
53
|
"31": 190
|
|
47
54
|
},
|
|
55
|
+
"statistical_ties": 0,
|
|
48
56
|
"suite_id": "T4GL-1024-v1"
|
|
49
57
|
}
|
|
50
58
|
},
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"build_driver": "580.82.07",
|
|
3
|
+
"build_nvcc": "Cuda compilation tools, release 12.8, V12.8.93",
|
|
4
|
+
"certification_member": "g4s1_certification.json",
|
|
5
|
+
"certified_integer_replay_bundle_sha256": "bee490cd5772e7fe2f222361febf18457ffd3aeec071ba3f0def8542d0c9bfc6",
|
|
6
|
+
"integer_replay_bundle_sha256": "bee490cd5772e7fe2f222361febf18457ffd3aeec071ba3f0def8542d0c9bfc6",
|
|
7
|
+
"certified_matmul_bundle_sha256": "0e0065f53f0f4809d4e9ec67a780af8a2b7fe8923ad057a77df60133ec17afe2",
|
|
8
|
+
"certified_runtime_zip_sha256": "af48bf21252f439bf97251d9411e6833b6f176790f7e0e6905f2a68f3ed2d221",
|
|
9
|
+
"compile": {
|
|
10
|
+
"arch": "sm_75",
|
|
11
|
+
"common": [
|
|
12
|
+
"-O3",
|
|
13
|
+
"-std=c++17",
|
|
14
|
+
"-arch=sm_75",
|
|
15
|
+
"-Xcompiler=-ffunction-sections",
|
|
16
|
+
"-Xcompiler=-fdata-sections",
|
|
17
|
+
"-Xlinker=--gc-sections"
|
|
18
|
+
],
|
|
19
|
+
"libraries": ["-lcublasLt", "-lcublas"],
|
|
20
|
+
"shared_extra": ["-shared", "-Xcompiler=-fPIC"]
|
|
21
|
+
},
|
|
22
|
+
"compute_capability": "7.5",
|
|
23
|
+
"frozen_final_ledger_sha256": "5415bf02bd435d542f402f0c97ed74efca03b6e1c8ca99695c8a296d814936ca",
|
|
24
|
+
"frozen_integer_exact_wins": 938,
|
|
25
|
+
"frozen_integer_nvidia_wins": 86,
|
|
26
|
+
"full_validation_report_sha256": "6c1229e501ac34fbbe61425e2b78c6fd7cb8ff0b26685d87ecf1ab97b906ea56",
|
|
27
|
+
"hardware": "Tesla T4",
|
|
28
|
+
"integer_sources": {
|
|
29
|
+
"direct": "source/rns_integer_direct_replay.cu",
|
|
30
|
+
"fused": "source/rns_integer_fused_replay.cu",
|
|
31
|
+
"generic": "source/rns_integer_generic_replay.cu",
|
|
32
|
+
"row": "source/rns_integer_row_replay.cu",
|
|
33
|
+
"splitk": "source/rns_integer_splitk_replay.cu",
|
|
34
|
+
"strip": "source/rns_integer_strip_replay.cu"
|
|
35
|
+
},
|
|
36
|
+
"matmul_sources": {
|
|
37
|
+
"direct": "source/rns_g4s1_matmul_direct.cu",
|
|
38
|
+
"fused": "source/rns_g4s1_matmul_fused.cu",
|
|
39
|
+
"generic": "source/rns_g4s1_matmul_generic.cu",
|
|
40
|
+
"row": "source/rns_g4s1_matmul_row.cu",
|
|
41
|
+
"splitk": "source/rns_g4s1_matmul_splitk.cu",
|
|
42
|
+
"strip": "source/rns_g4s1_matmul_strip.cu"
|
|
43
|
+
},
|
|
44
|
+
"members_sha256": {
|
|
45
|
+
"g4s1_certification.json": "292a4e31abdbf99d0b8854879c23502bc5d3fb58e96ddf920cb3627114728931",
|
|
46
|
+
"g4s1_matmul_shapes.json": "ac612da046601fa0f2a6e23f3ddcf58d5d91699cef3a9263a5a00118ccbb2873",
|
|
47
|
+
"source/rns_g4s1_matmul_direct.cu": "d9c803213314237e8a945c63a0fea59e557d67329e32a626529088e9ccb1f4b0",
|
|
48
|
+
"source/rns_g4s1_matmul_fused.cu": "b7586b123002b92d045497c9127daabab1cd5ef93ec69d4ef8ee12cbc1409bca",
|
|
49
|
+
"source/rns_g4s1_matmul_generic.cu": "c47b4869b4af9f68027664a41e436613425b2ac0e211f297bcd6de813abf8a0b",
|
|
50
|
+
"source/rns_g4s1_matmul_row.cu": "bc0ed2d148aa0bc7112db18b622995051a8b70c3e9ef0805d43218183e9b9570",
|
|
51
|
+
"source/rns_g4s1_matmul_splitk.cu": "0a6ffc121f0211d7e9f620000cfce78ad61df4d6bca4918026ec397c2f9078b9",
|
|
52
|
+
"source/rns_g4s1_matmul_strip.cu": "6ca0ad58cc7f54fe3d3b5534479b52bb00d0d8d09f26d9bd53daf64c83bd85eb",
|
|
53
|
+
"source/rns_integer_direct_replay.cu": "d2206214cfe5d74110c5fd2b50c3db7ee1d6bd10ecc8171569869c1fd32ed1ff",
|
|
54
|
+
"source/rns_integer_fused_replay.cu": "f4ec25c6425d1d7e9aa2bdb5be893a5a89ee780e4b45c58a52a9b23a98d153d9",
|
|
55
|
+
"source/rns_integer_generic_replay.cu": "023abff6b8cd7c289e68a7b69b9bc585dc463a8618ddf43979458e8fecbe6252",
|
|
56
|
+
"source/rns_integer_row_replay.cu": "fa8f0e62462e8ea4aa1f1ba718430adf5ea87a6de92755f6c8524021048191f8",
|
|
57
|
+
"source/rns_integer_splitk_replay.cu": "c9a9c431c33dbcfa452c493a2f31c4d724d9bc112d40fc90f71691c3c6d6e544",
|
|
58
|
+
"source/rns_integer_strip_replay.cu": "f4dadbb2d394d9e567f1571c347186ee163599495b6c1ceb69dd253087d5f2dc"
|
|
59
|
+
},
|
|
60
|
+
"modes": {"full": 1024, "quick": 24, "standard": 128},
|
|
61
|
+
"numeric_contract": {
|
|
62
|
+
"integer_inputs": "signed int8 matrices",
|
|
63
|
+
"integer_output": "exact signed int32 matrix",
|
|
64
|
+
"rational_inputs": "SharedScaleMatrix with signed-int8 numerators and positive integer shared scale",
|
|
65
|
+
"rational_output": "exact SharedScaleMatrix; output scale = left.scale * right.scale"
|
|
66
|
+
},
|
|
67
|
+
"payload_format": "base64+xz+tar-public-execution-source",
|
|
68
|
+
"payload_part_sha256": {
|
|
69
|
+
"g4s1_public_t4_source_c01.b64": "711118bd11d34ffdac24f30dc46fca232824d280fc449f86e18011d4f0f94c8c",
|
|
70
|
+
"g4s1_public_t4_source_c02.b64": "36700ed0b2daa8f227d5a04006d02e5c77c54e5c32276f0ede47251eb0e95b68",
|
|
71
|
+
"g4s1_public_t4_source_c03.b64": "3cb42f61086ccd5335a68824af05f02e80dcaa006213e6e80d12a0c87a02c2de",
|
|
72
|
+
"g4s1_public_t4_source_c04.b64": "a77718c4b5233661d6a05372b7d9d56975ab489da181a3fdcead45d26037ccb4",
|
|
73
|
+
"g4s1_public_t4_source_c05.b64": "badf4ee7faa8516235af07389995c5cc622aff0bc03b34cc2c405ed737c31aaa",
|
|
74
|
+
"g4s1_public_t4_source_c06.b64": "aa209b529c23eb869c2384d4365581f8e23db2b98db19163f6d54414596bf498",
|
|
75
|
+
"g4s1_public_t4_source_c07.b64": "f3a9935a01ebfee5f48549da523e6b122f90e353f97340c74849a2dec87728c9",
|
|
76
|
+
"g4s1_public_t4_source_c08.b64": "97806a8395e8fe8b5bb043b4aeec097b05a66d206ea595e990fb7fd13e44c1b9",
|
|
77
|
+
"g4s1_public_t4_source_c09.b64": "cb7ac95d182c633008711a06d633f3a773511985d00e1d4c1ff3d32e784137fc",
|
|
78
|
+
"g4s1_public_t4_source_c10.b64": "a37239f5c7b845c5a64575403e2534080711dd0ae54ed6e434840a48a2d25282",
|
|
79
|
+
"g4s1_public_t4_source_c11.b64": "f7b83d4fd96c71602f13ce63a341bc71171a3ed3c23f342ec68877984d90a7dc",
|
|
80
|
+
"g4s1_public_t4_source_c12.b64": "b1af397f57f368ac0de09a650fdb6bbb1499240979d01eccec1f8d47ab64201d"
|
|
81
|
+
},
|
|
82
|
+
"payload_parts": [
|
|
83
|
+
"g4s1_public_t4_source_c01.b64", "g4s1_public_t4_source_c02.b64", "g4s1_public_t4_source_c03.b64",
|
|
84
|
+
"g4s1_public_t4_source_c04.b64", "g4s1_public_t4_source_c05.b64", "g4s1_public_t4_source_c06.b64",
|
|
85
|
+
"g4s1_public_t4_source_c07.b64", "g4s1_public_t4_source_c08.b64", "g4s1_public_t4_source_c09.b64",
|
|
86
|
+
"g4s1_public_t4_source_c10.b64", "g4s1_public_t4_source_c11.b64", "g4s1_public_t4_source_c12.b64"
|
|
87
|
+
],
|
|
88
|
+
"payload_sha256": "3db92b68fe11322977d784ed05852f74e3d334751826895a5b122d7f9d99f6f3",
|
|
89
|
+
"privacy_boundary": "public execution sources only; G4 search, candidate generation, grammar, learner, and optimization machinery are not included",
|
|
90
|
+
"schema": "RNS-ENGINE-G4S1-PUBLIC-T4-SOURCE-RUNTIME-1",
|
|
91
|
+
"series": 1,
|
|
92
|
+
"shape_manifest_member": "g4s1_matmul_shapes.json",
|
|
93
|
+
"source_archive_sha256": "b9f97f8e5d45956cc431665b0fbf7b990b1ef18b78b7c1859f1d827cd8d73dda",
|
|
94
|
+
"supported_shapes": 1024,
|
|
95
|
+
"tar_sha256": "f7fc87d3c002ae492cb860eb44910f4097bdbaf8f3be6d9f302ce56bedfff2e0",
|
|
96
|
+
"xz_sha256": "6b361d2eb6714b470f0fec18646ee9f7590b832bb814aff19eab94a19b4caf3e"
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
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
|