tensorstudio 1.5.1__tar.gz → 1.7.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.
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/CHANGELOG.md +43 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/CMakeLists.txt +18 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/PKG-INFO +67 -28
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/README.md +66 -27
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmark_all.py +30 -2
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/benchmark_report.py +50 -2
- tensorstudio-1.7.0/benchmarks/results.md +347 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_conv2d.md +39 -39
- tensorstudio-1.7.0/benchmarks/results_matmul.md +49 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_pooling.md +45 -45
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_reductions.md +75 -75
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_tensor_ops.md +309 -309
- tensorstudio-1.7.0/benchmarks/thresholds.json +49 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/autograd/coverage.md +9 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/api-reference.md +65 -0
- tensorstudio-1.7.0/docs/core/math-and-statistics.md +171 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/tensors.md +33 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/getting-started/quickstart.md +29 -2
- tensorstudio-1.7.0/docs/hardware/cpu-backend.md +84 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/hardware/linux.md +18 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/hardware/macos.md +15 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/hardware/windows.md +22 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/index.md +11 -8
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/onnx.md +1 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/serialization.md +1 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/training.md +2 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/performance/benchmarks.md +21 -7
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/performance/optimization.md +24 -6
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/release/publishing.md +4 -4
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/release/versioning.md +2 -2
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/roadmap/milestones.md +3 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/roadmap/roadmap.md +31 -20
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/ops.hpp +13 -0
- tensorstudio-1.7.0/include/tensorstudio/perf.hpp +34 -0
- tensorstudio-1.7.0/include/tensorstudio/random.hpp +36 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/storage.hpp +2 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/version.hpp +1 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/mkdocs.yml +1 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/pyproject.toml +1 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/_C.pyi +56 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/__init__.py +41 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/_version.py +1 -1
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/math.py +87 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/functional.py +4 -5
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/ops.py +60 -0
- tensorstudio-1.7.0/python/tensorstudio/performance.py +39 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/tensor.py +120 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_ops.cpp +51 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_tensor.cpp +148 -11
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bindings.cpp +15 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/ops.cpp +613 -78
- tensorstudio-1.7.0/src/core/perf.cpp +250 -0
- tensorstudio-1.7.0/src/core/random.cpp +107 -0
- tensorstudio-1.7.0/src/core/storage.cpp +116 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_benchmark_report.py +26 -1
- tensorstudio-1.7.0/tests/test_core_math_expansion.py +156 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_import.py +1 -1
- tensorstudio-1.7.0/tests/test_performance.py +43 -0
- tensorstudio-1.5.1/benchmarks/results.md +0 -343
- tensorstudio-1.5.1/benchmarks/results_matmul.md +0 -45
- tensorstudio-1.5.1/docs/hardware/cpu-backend.md +0 -40
- tensorstudio-1.5.1/include/tensorstudio/random.hpp +0 -13
- tensorstudio-1.5.1/src/core/random.cpp +0 -54
- tensorstudio-1.5.1/src/core/storage.cpp +0 -29
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.gitattributes +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/ci.yml +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/publish-testpypi.yml +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/publish.yml +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/wheels.yml +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.gitignore +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.pre-commit-config.yaml +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/CONTRIBUTING.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/LICENSE +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/SECURITY.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_activations.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_autograd.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_conv2d.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_elementwise.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_matmul.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_pooling.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_reductions.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_tensor_ops.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_training_loop.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/autograd/gradient-notes.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/autograd/overview.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/broadcasting.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/native-cpp-core.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/data/dataloader-patterns.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/data/datasets-and-dataloaders.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/data/tensor-datasets.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/development/contributing.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/development/cpp-first.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/getting-started/installation.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/getting-started/source-build.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/model-formats.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/numpy-interop.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/trusted-serialization.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/modules.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/optimizers.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/overview.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/performance/profiling.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/project/checkpoints.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/project/project-layout.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/project/workflows.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/release/checklist.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/roadmap/priorities.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/vision/dataset-creation.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/vision/overview.md +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/basic_tensor_ops.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/export_onnx.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/image_folder_classification.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/linear_regression.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/project_training.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/save_load_model.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/tiny_mlp.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/vision_classifier.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/autograd.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/device.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/dtype.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/errors.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/module.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/optim.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/serialization.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/shape.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/tensor.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/autograd.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/data/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/data/dataloader.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/data/dataset.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/dtypes.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/errors.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/grad_mode.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/interchange/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/interchange/onnx.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/losses.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/modules.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/adam.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/adamw.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/lr_scheduler.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/sgd.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/utils.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/checkpoint.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/config.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/trainer.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/py.typed +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/serialization.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/typing.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/__init__.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/datasets.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/io.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/metrics.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/models.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/transforms.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/visualization.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_autograd.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_nn.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_optim.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bindings.hpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/autograd.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/device.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/dtype.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/errors.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/module.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/optim.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/serialization.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/shape.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/tensor.cpp +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/test_all.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_autograd.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_broadcasting.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_data.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_errors.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_indexing.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_interchange.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_nn.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_numpy_interop.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_ops.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_optim.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_project.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_serialization.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_tensor.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_views.py +0 -0
- {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_vision.py +0 -0
|
@@ -2,6 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 1.7.0 - 2026-07-07
|
|
6
|
+
|
|
7
|
+
- Completed the ordered Core Math Expansion roadmap section as one release
|
|
8
|
+
batch.
|
|
9
|
+
- Added native C++ `logsumexp`, `softmax`, and `log_softmax` operations with
|
|
10
|
+
max-shifted stable numerics and autograd support.
|
|
11
|
+
- Added native C++ batched matrix multiplication through `bmm` and 3D `@`
|
|
12
|
+
dispatch, including reverse-mode gradients for both operands.
|
|
13
|
+
- Added native C++ `var`, `variance`, `std`, `all`, and `any` operations, plus
|
|
14
|
+
Tensor methods and top-level Python exports where appropriate.
|
|
15
|
+
- Added Tensor-level `norm()` and expanded `tensorstudio.math` with
|
|
16
|
+
`logsumexp`, `softmax`, `log_softmax`, boolean reductions, and a documented
|
|
17
|
+
practical `einsum` subset.
|
|
18
|
+
- Added seeded native random distributions: `uniform`, `normal`, `randint`,
|
|
19
|
+
and `bernoulli`, with Python `*_like` helpers where useful.
|
|
20
|
+
- Switched neural-network functional softmax/log-softmax and cross entropy to
|
|
21
|
+
the native stable kernels.
|
|
22
|
+
- Added NumPy parity and autograd tests for the expanded math surface.
|
|
23
|
+
|
|
24
|
+
## 1.6.0 - 2026-07-07
|
|
25
|
+
|
|
26
|
+
- Completed the ordered CPU Performance Core roadmap section as one release
|
|
27
|
+
batch.
|
|
28
|
+
- Added optional CBLAS/Accelerate-backed `matmul` for contiguous `float32` and
|
|
29
|
+
`float64` matrices when the source build environment exposes a compatible
|
|
30
|
+
BLAS library and header; portable C++ kernels remain the fallback path.
|
|
31
|
+
- Added a small native C++ CPU thread pool, configurable with
|
|
32
|
+
`tensorstudio.set_num_threads()` and `TENSORSTUDIO_NUM_THREADS`, and used it
|
|
33
|
+
for large contiguous elementwise ops, reductions, matrix multiplication,
|
|
34
|
+
convolution, and pooling forward kernels.
|
|
35
|
+
- Added SIMD-friendly typed `float32`/`float64` contiguous kernels for common
|
|
36
|
+
elementwise arithmetic and activations, while preserving mixed-dtype fallback
|
|
37
|
+
behavior.
|
|
38
|
+
- Added a bounded C++ storage reuse pool for tensor allocations, with
|
|
39
|
+
`TENSORSTUDIO_DISABLE_STORAGE_POOL=1` and
|
|
40
|
+
`TENSORSTUDIO_STORAGE_POOL_MAX_BLOCK_BYTES` controls.
|
|
41
|
+
- Added `tensorstudio.performance_info()`, `get_num_threads()`, and
|
|
42
|
+
`set_num_threads()` diagnostics/configuration helpers.
|
|
43
|
+
- Added benchmark threshold support via `benchmark_all.py --check-thresholds`
|
|
44
|
+
and `benchmarks/thresholds.json`.
|
|
45
|
+
- Expanded performance, CPU backend, and platform docs for BLAS selection,
|
|
46
|
+
threading, storage reuse, benchmark thresholds, and honest interpretation.
|
|
47
|
+
|
|
5
48
|
## 1.5.1 - 2026-07-07
|
|
6
49
|
|
|
7
50
|
- Completed the next ordered correctness-roadmap item with clearer native
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.18)
|
|
2
2
|
|
|
3
|
-
project(tensorstudio VERSION 1.
|
|
3
|
+
project(tensorstudio VERSION 1.7.0 LANGUAGES CXX)
|
|
4
4
|
|
|
5
5
|
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
|
|
6
6
|
set(PYBIND11_FINDPYTHON ON)
|
|
7
7
|
find_package(pybind11 CONFIG REQUIRED)
|
|
8
8
|
|
|
9
|
+
option(TENSORSTUDIO_ENABLE_BLAS "Enable optional CBLAS-backed matmul when available" ON)
|
|
10
|
+
|
|
9
11
|
set(TENSORSTUDIO_CORE_SOURCES
|
|
10
12
|
src/core/tensor.cpp
|
|
11
13
|
src/core/dtype.cpp
|
|
@@ -19,6 +21,7 @@ set(TENSORSTUDIO_CORE_SOURCES
|
|
|
19
21
|
src/core/random.cpp
|
|
20
22
|
src/core/serialization.cpp
|
|
21
23
|
src/core/errors.cpp
|
|
24
|
+
src/core/perf.cpp
|
|
22
25
|
)
|
|
23
26
|
|
|
24
27
|
set(TENSORSTUDIO_BINDING_SOURCES
|
|
@@ -38,6 +41,20 @@ pybind11_add_module(_C MODULE
|
|
|
38
41
|
target_include_directories(_C PRIVATE include src/bindings)
|
|
39
42
|
target_compile_features(_C PRIVATE cxx_std_20)
|
|
40
43
|
|
|
44
|
+
if(TENSORSTUDIO_ENABLE_BLAS)
|
|
45
|
+
find_package(BLAS)
|
|
46
|
+
if(BLAS_FOUND)
|
|
47
|
+
include(CheckIncludeFileCXX)
|
|
48
|
+
check_include_file_cxx(cblas.h TENSORSTUDIO_HAVE_CBLAS_H)
|
|
49
|
+
target_link_libraries(_C PRIVATE ${BLAS_LIBRARIES})
|
|
50
|
+
if(APPLE)
|
|
51
|
+
target_compile_definitions(_C PRIVATE TENSORSTUDIO_HAS_ACCELERATE=1)
|
|
52
|
+
elseif(TENSORSTUDIO_HAVE_CBLAS_H)
|
|
53
|
+
target_compile_definitions(_C PRIVATE TENSORSTUDIO_HAS_CBLAS=1)
|
|
54
|
+
endif()
|
|
55
|
+
endif()
|
|
56
|
+
endif()
|
|
57
|
+
|
|
41
58
|
if(MSVC)
|
|
42
59
|
target_compile_options(_C PRIVATE /W4 /permissive-)
|
|
43
60
|
else()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tensorstudio
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: TensorStudio is a compact C++ tensor and autograd engine with a Python API for learning, experimentation, and lightweight ML workloads.
|
|
5
5
|
Keywords: tensor,autograd,machine-learning,cpp,pybind11
|
|
6
6
|
Author: TensorStudio contributors
|
|
@@ -71,8 +71,12 @@ Description-Content-Type: text/markdown
|
|
|
71
71
|
TensorStudio is a compact C++ tensor and autograd engine with a Python API for
|
|
72
72
|
learning, experimentation, and lightweight ML workloads.
|
|
73
73
|
|
|
74
|
-
TensorStudio `1.
|
|
75
|
-
|
|
74
|
+
TensorStudio `1.7.0` is a CPU-only stable API foundation with native C++
|
|
75
|
+
threading, storage reuse, SIMD-friendly typed kernels, and optional
|
|
76
|
+
CBLAS/Accelerate matrix multiplication when available. It adds native stable
|
|
77
|
+
softmax/logsumexp, batched matrix multiplication, statistical reductions,
|
|
78
|
+
boolean reductions, and seeded random distributions. It is eager-only,
|
|
79
|
+
intentionally compact, and not a replacement for mature ML frameworks.
|
|
76
80
|
|
|
77
81
|
## Install
|
|
78
82
|
|
|
@@ -163,12 +167,15 @@ a = ts.zeros((2, 3))
|
|
|
163
167
|
b = ts.rand((2, 3))
|
|
164
168
|
c = ts.eye(3)
|
|
165
169
|
d = ts.linspace(0.0, 1.0, 5)
|
|
170
|
+
labels = ts.randint((4,), low=0, high=3, seed=3)
|
|
171
|
+
mask = ts.bernoulli((2, 3), probability=0.25, seed=5)
|
|
166
172
|
|
|
167
173
|
print(a.shape, a.strides, a.device, a.is_contiguous)
|
|
168
174
|
print((b.clamp(0.2, 0.8) + 1).mean().item())
|
|
169
175
|
print(b.sum(axis=1).tolist())
|
|
170
176
|
print(ts.concat([b, b], axis=0).shape, b.astype("float64").dtype)
|
|
171
177
|
print(c.tolist(), d.tolist())
|
|
178
|
+
print(labels.tolist(), mask.any(axis=1).tolist())
|
|
172
179
|
print(ts.zeros_like(b).shape, ts.randn_like(b, seed=11).dtype)
|
|
173
180
|
```
|
|
174
181
|
|
|
@@ -197,14 +204,29 @@ print(loss.item())
|
|
|
197
204
|
print(x.grad.tolist())
|
|
198
205
|
```
|
|
199
206
|
|
|
200
|
-
|
|
207
|
+
Stable reductions and normalized probabilities are available as Tensor methods,
|
|
208
|
+
functional ops, and `tensorstudio.math` helpers:
|
|
201
209
|
|
|
202
210
|
```python
|
|
203
|
-
values = ts.tensor([[
|
|
211
|
+
values = ts.tensor([[1000.0, 1001.0, 999.0], [1.0, 2.0, 3.0]])
|
|
204
212
|
|
|
205
213
|
print(ts.math.variance(values).item())
|
|
206
214
|
print(ts.math.std(values, axis=0).tolist())
|
|
207
215
|
print(ts.math.norm(values, ord=2).item())
|
|
216
|
+
print(values.softmax(axis=1).tolist())
|
|
217
|
+
print(ts.logsumexp(values, axis=1).tolist())
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Batched matrix multiplication and a small documented `einsum` subset cover
|
|
221
|
+
common model and scientific-programming patterns:
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
left = ts.randn((2, 3, 4), seed=1)
|
|
225
|
+
right = ts.randn((2, 4, 5), seed=2)
|
|
226
|
+
|
|
227
|
+
print((left @ right).shape)
|
|
228
|
+
print(ts.bmm(left, right).shape)
|
|
229
|
+
print(ts.einsum("bij,bjk->bik", left, right).shape)
|
|
208
230
|
```
|
|
209
231
|
|
|
210
232
|
## Autograd
|
|
@@ -344,31 +366,46 @@ python benchmarks/benchmark_report.py
|
|
|
344
366
|
columns for NumPy, TensorFlow, PyTorch, and JAX when those libraries are
|
|
345
367
|
available locally.
|
|
346
368
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
369
|
+
Useful runtime diagnostics:
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
import tensorstudio as ts
|
|
373
|
+
|
|
374
|
+
print(ts.performance_info())
|
|
375
|
+
ts.set_num_threads(4)
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Run the loose local regression thresholds with:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
python benchmark_all.py --check-thresholds
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
On one Windows CPython 3.10 development run reporting `1.7.0`, with
|
|
385
|
+
TensorStudio threads enabled, storage pooling enabled, SSE2 autovectorization
|
|
386
|
+
reported, and no BLAS provider found, TensorStudio beat NumPy on 7 local
|
|
387
|
+
benchmark cases and lost on 96 NumPy-comparable cases. JAX CPU dispatch was
|
|
388
|
+
available on that machine; TensorStudio won 45 local cases and lost 53. The
|
|
389
|
+
strongest local wins were the simple NumPy convolution/pooling reference loops
|
|
390
|
+
and some small JAX-dispatch-heavy eager cases. NumPy and JAX were faster for
|
|
391
|
+
many elementwise, reduction, matrix multiplication, larger activation, and
|
|
392
|
+
autograd workloads.
|
|
356
393
|
See `benchmarks/results.md` for the full table, platform details, and exact
|
|
357
394
|
timings.
|
|
358
395
|
|
|
359
396
|
Snapshot from that local run:
|
|
360
397
|
|
|
361
|
-
| operation | shape | TensorStudio | NumPy |
|
|
398
|
+
| operation | shape | TensorStudio | NumPy | JAX CPU dispatch | TS vs NumPy | TS vs JAX |
|
|
362
399
|
|---|---:|---:|---:|---:|---:|---:|
|
|
363
|
-
| `sigmoid` | `(32,)` | 0.
|
|
364
|
-
| `mean` | `(32,)` | 0.
|
|
365
|
-
| `sum_axis1` | `(16, 16)` | 0.
|
|
366
|
-
| `chain_relu` | `(128,)` | 0.
|
|
367
|
-
| `matmul` | `(256, 256)` |
|
|
368
|
-
| `conv2d_3x3_padding1` | `(1, 1, 8, 8)` | 0.
|
|
369
|
-
| `max_pool2d_2x2` | `(1, 1, 16, 16)` | 0.
|
|
370
|
-
| `avg_pool2d_2x2` | `(1, 1, 16, 16)` | 0.
|
|
371
|
-
| `elementwise_backward` | `(1024,)` |
|
|
400
|
+
| `sigmoid` | `(32,)` | 0.0152 ms | 0.0044 ms | 0.0727 ms | 0.2909x | 4.7701x |
|
|
401
|
+
| `mean` | `(32,)` | 0.0177 ms | 0.0083 ms | 0.0113 ms | 0.4715x | 0.6400x |
|
|
402
|
+
| `sum_axis1` | `(16, 16)` | 0.0163 ms | 0.0031 ms | 0.0123 ms | 0.1901x | 0.7536x |
|
|
403
|
+
| `chain_relu` | `(128,)` | 0.0867 ms | 0.0062 ms | 0.0923 ms | 0.0721x | 1.0641x |
|
|
404
|
+
| `matmul` | `(256, 256)` | 2.2252 ms | 0.4754 ms | 0.2750 ms | 0.2136x | 0.1236x |
|
|
405
|
+
| `conv2d_3x3_padding1` | `(1, 1, 8, 8)` | 0.1915 ms | 1.2845 ms | 0.1081 ms | 6.7064x | 0.5646x |
|
|
406
|
+
| `max_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0277 ms | 0.1577 ms | n/a | 5.7024x | n/a |
|
|
407
|
+
| `avg_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0278 ms | 0.5538 ms | n/a | 19.8919x | n/a |
|
|
408
|
+
| `elementwise_backward` | `(1024,)` | 2.7344 ms | n/a | n/a | n/a | n/a |
|
|
372
409
|
|
|
373
410
|
Speedup is `competitor median / TensorStudio median`, so values above `1.0x`
|
|
374
411
|
favor TensorStudio.
|
|
@@ -465,7 +502,9 @@ tokens or print secrets.
|
|
|
465
502
|
- CPU backend only.
|
|
466
503
|
- Eager execution only.
|
|
467
504
|
- No CUDA or Metal backend yet.
|
|
468
|
-
-
|
|
505
|
+
- Optional BLAS-backed matrix multiplication depends on the build environment
|
|
506
|
+
exposing a compatible CBLAS/Accelerate interface; otherwise TensorStudio uses
|
|
507
|
+
a portable C++ fallback.
|
|
469
508
|
- No graph compiler or distributed runtime.
|
|
470
509
|
- Convolution and pooling support are currently limited to CPU NCHW
|
|
471
510
|
`conv2d`, `max_pool2d`, and `avg_pool2d` style workloads.
|
|
@@ -495,9 +534,9 @@ tokens or print secrets.
|
|
|
495
534
|
- Richer dataset utilities
|
|
496
535
|
- Model zoo examples
|
|
497
536
|
- ONNX import and broader export coverage
|
|
498
|
-
-
|
|
499
|
-
-
|
|
500
|
-
-
|
|
537
|
+
- Runtime-dispatched SIMD kernels
|
|
538
|
+
- Better non-BLAS matrix multiplication tiling
|
|
539
|
+
- More threaded backward kernels
|
|
501
540
|
|
|
502
541
|
## License
|
|
503
542
|
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
TensorStudio is a compact C++ tensor and autograd engine with a Python API for
|
|
8
8
|
learning, experimentation, and lightweight ML workloads.
|
|
9
9
|
|
|
10
|
-
TensorStudio `1.
|
|
11
|
-
|
|
10
|
+
TensorStudio `1.7.0` is a CPU-only stable API foundation with native C++
|
|
11
|
+
threading, storage reuse, SIMD-friendly typed kernels, and optional
|
|
12
|
+
CBLAS/Accelerate matrix multiplication when available. It adds native stable
|
|
13
|
+
softmax/logsumexp, batched matrix multiplication, statistical reductions,
|
|
14
|
+
boolean reductions, and seeded random distributions. It is eager-only,
|
|
15
|
+
intentionally compact, and not a replacement for mature ML frameworks.
|
|
12
16
|
|
|
13
17
|
## Install
|
|
14
18
|
|
|
@@ -99,12 +103,15 @@ a = ts.zeros((2, 3))
|
|
|
99
103
|
b = ts.rand((2, 3))
|
|
100
104
|
c = ts.eye(3)
|
|
101
105
|
d = ts.linspace(0.0, 1.0, 5)
|
|
106
|
+
labels = ts.randint((4,), low=0, high=3, seed=3)
|
|
107
|
+
mask = ts.bernoulli((2, 3), probability=0.25, seed=5)
|
|
102
108
|
|
|
103
109
|
print(a.shape, a.strides, a.device, a.is_contiguous)
|
|
104
110
|
print((b.clamp(0.2, 0.8) + 1).mean().item())
|
|
105
111
|
print(b.sum(axis=1).tolist())
|
|
106
112
|
print(ts.concat([b, b], axis=0).shape, b.astype("float64").dtype)
|
|
107
113
|
print(c.tolist(), d.tolist())
|
|
114
|
+
print(labels.tolist(), mask.any(axis=1).tolist())
|
|
108
115
|
print(ts.zeros_like(b).shape, ts.randn_like(b, seed=11).dtype)
|
|
109
116
|
```
|
|
110
117
|
|
|
@@ -133,14 +140,29 @@ print(loss.item())
|
|
|
133
140
|
print(x.grad.tolist())
|
|
134
141
|
```
|
|
135
142
|
|
|
136
|
-
|
|
143
|
+
Stable reductions and normalized probabilities are available as Tensor methods,
|
|
144
|
+
functional ops, and `tensorstudio.math` helpers:
|
|
137
145
|
|
|
138
146
|
```python
|
|
139
|
-
values = ts.tensor([[
|
|
147
|
+
values = ts.tensor([[1000.0, 1001.0, 999.0], [1.0, 2.0, 3.0]])
|
|
140
148
|
|
|
141
149
|
print(ts.math.variance(values).item())
|
|
142
150
|
print(ts.math.std(values, axis=0).tolist())
|
|
143
151
|
print(ts.math.norm(values, ord=2).item())
|
|
152
|
+
print(values.softmax(axis=1).tolist())
|
|
153
|
+
print(ts.logsumexp(values, axis=1).tolist())
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Batched matrix multiplication and a small documented `einsum` subset cover
|
|
157
|
+
common model and scientific-programming patterns:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
left = ts.randn((2, 3, 4), seed=1)
|
|
161
|
+
right = ts.randn((2, 4, 5), seed=2)
|
|
162
|
+
|
|
163
|
+
print((left @ right).shape)
|
|
164
|
+
print(ts.bmm(left, right).shape)
|
|
165
|
+
print(ts.einsum("bij,bjk->bik", left, right).shape)
|
|
144
166
|
```
|
|
145
167
|
|
|
146
168
|
## Autograd
|
|
@@ -280,31 +302,46 @@ python benchmarks/benchmark_report.py
|
|
|
280
302
|
columns for NumPy, TensorFlow, PyTorch, and JAX when those libraries are
|
|
281
303
|
available locally.
|
|
282
304
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
305
|
+
Useful runtime diagnostics:
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
import tensorstudio as ts
|
|
309
|
+
|
|
310
|
+
print(ts.performance_info())
|
|
311
|
+
ts.set_num_threads(4)
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Run the loose local regression thresholds with:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
python benchmark_all.py --check-thresholds
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
On one Windows CPython 3.10 development run reporting `1.7.0`, with
|
|
321
|
+
TensorStudio threads enabled, storage pooling enabled, SSE2 autovectorization
|
|
322
|
+
reported, and no BLAS provider found, TensorStudio beat NumPy on 7 local
|
|
323
|
+
benchmark cases and lost on 96 NumPy-comparable cases. JAX CPU dispatch was
|
|
324
|
+
available on that machine; TensorStudio won 45 local cases and lost 53. The
|
|
325
|
+
strongest local wins were the simple NumPy convolution/pooling reference loops
|
|
326
|
+
and some small JAX-dispatch-heavy eager cases. NumPy and JAX were faster for
|
|
327
|
+
many elementwise, reduction, matrix multiplication, larger activation, and
|
|
328
|
+
autograd workloads.
|
|
292
329
|
See `benchmarks/results.md` for the full table, platform details, and exact
|
|
293
330
|
timings.
|
|
294
331
|
|
|
295
332
|
Snapshot from that local run:
|
|
296
333
|
|
|
297
|
-
| operation | shape | TensorStudio | NumPy |
|
|
334
|
+
| operation | shape | TensorStudio | NumPy | JAX CPU dispatch | TS vs NumPy | TS vs JAX |
|
|
298
335
|
|---|---:|---:|---:|---:|---:|---:|
|
|
299
|
-
| `sigmoid` | `(32,)` | 0.
|
|
300
|
-
| `mean` | `(32,)` | 0.
|
|
301
|
-
| `sum_axis1` | `(16, 16)` | 0.
|
|
302
|
-
| `chain_relu` | `(128,)` | 0.
|
|
303
|
-
| `matmul` | `(256, 256)` |
|
|
304
|
-
| `conv2d_3x3_padding1` | `(1, 1, 8, 8)` | 0.
|
|
305
|
-
| `max_pool2d_2x2` | `(1, 1, 16, 16)` | 0.
|
|
306
|
-
| `avg_pool2d_2x2` | `(1, 1, 16, 16)` | 0.
|
|
307
|
-
| `elementwise_backward` | `(1024,)` |
|
|
336
|
+
| `sigmoid` | `(32,)` | 0.0152 ms | 0.0044 ms | 0.0727 ms | 0.2909x | 4.7701x |
|
|
337
|
+
| `mean` | `(32,)` | 0.0177 ms | 0.0083 ms | 0.0113 ms | 0.4715x | 0.6400x |
|
|
338
|
+
| `sum_axis1` | `(16, 16)` | 0.0163 ms | 0.0031 ms | 0.0123 ms | 0.1901x | 0.7536x |
|
|
339
|
+
| `chain_relu` | `(128,)` | 0.0867 ms | 0.0062 ms | 0.0923 ms | 0.0721x | 1.0641x |
|
|
340
|
+
| `matmul` | `(256, 256)` | 2.2252 ms | 0.4754 ms | 0.2750 ms | 0.2136x | 0.1236x |
|
|
341
|
+
| `conv2d_3x3_padding1` | `(1, 1, 8, 8)` | 0.1915 ms | 1.2845 ms | 0.1081 ms | 6.7064x | 0.5646x |
|
|
342
|
+
| `max_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0277 ms | 0.1577 ms | n/a | 5.7024x | n/a |
|
|
343
|
+
| `avg_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0278 ms | 0.5538 ms | n/a | 19.8919x | n/a |
|
|
344
|
+
| `elementwise_backward` | `(1024,)` | 2.7344 ms | n/a | n/a | n/a | n/a |
|
|
308
345
|
|
|
309
346
|
Speedup is `competitor median / TensorStudio median`, so values above `1.0x`
|
|
310
347
|
favor TensorStudio.
|
|
@@ -401,7 +438,9 @@ tokens or print secrets.
|
|
|
401
438
|
- CPU backend only.
|
|
402
439
|
- Eager execution only.
|
|
403
440
|
- No CUDA or Metal backend yet.
|
|
404
|
-
-
|
|
441
|
+
- Optional BLAS-backed matrix multiplication depends on the build environment
|
|
442
|
+
exposing a compatible CBLAS/Accelerate interface; otherwise TensorStudio uses
|
|
443
|
+
a portable C++ fallback.
|
|
405
444
|
- No graph compiler or distributed runtime.
|
|
406
445
|
- Convolution and pooling support are currently limited to CPU NCHW
|
|
407
446
|
`conv2d`, `max_pool2d`, and `avg_pool2d` style workloads.
|
|
@@ -431,9 +470,9 @@ tokens or print secrets.
|
|
|
431
470
|
- Richer dataset utilities
|
|
432
471
|
- Model zoo examples
|
|
433
472
|
- ONNX import and broader export coverage
|
|
434
|
-
-
|
|
435
|
-
-
|
|
436
|
-
-
|
|
473
|
+
- Runtime-dispatched SIMD kernels
|
|
474
|
+
- Better non-BLAS matrix multiplication tiling
|
|
475
|
+
- More threaded backward kernels
|
|
437
476
|
|
|
438
477
|
## License
|
|
439
478
|
|
|
@@ -3,7 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
import argparse
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
-
from benchmarks.benchmark_report import
|
|
6
|
+
from benchmarks.benchmark_report import (
|
|
7
|
+
evaluate_thresholds,
|
|
8
|
+
load_thresholds,
|
|
9
|
+
render_benchmark_report,
|
|
10
|
+
run_benchmark_data,
|
|
11
|
+
write_benchmark_report,
|
|
12
|
+
)
|
|
7
13
|
|
|
8
14
|
ALL_SECTIONS = {
|
|
9
15
|
"elementwise",
|
|
@@ -36,14 +42,36 @@ def main() -> None:
|
|
|
36
42
|
action="store_true",
|
|
37
43
|
help="Print the full Markdown report after writing it.",
|
|
38
44
|
)
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--thresholds",
|
|
47
|
+
type=Path,
|
|
48
|
+
default=Path("benchmarks") / "thresholds.json",
|
|
49
|
+
help="Benchmark regression threshold file.",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--check-thresholds",
|
|
53
|
+
action="store_true",
|
|
54
|
+
help="Fail if TensorStudio median benchmark times exceed thresholds.",
|
|
55
|
+
)
|
|
39
56
|
args = parser.parse_args()
|
|
40
57
|
|
|
41
58
|
selected_sections = set(args.section or ALL_SECTIONS)
|
|
42
|
-
|
|
59
|
+
cases, libraries, results = run_benchmark_data(selected_sections)
|
|
60
|
+
report = render_benchmark_report(cases, libraries, results)
|
|
61
|
+
write_benchmark_report(report, args.output)
|
|
43
62
|
if args.print:
|
|
44
63
|
print(report)
|
|
45
64
|
else:
|
|
46
65
|
print(f"Wrote benchmark report to {args.output}")
|
|
66
|
+
if args.check_thresholds:
|
|
67
|
+
thresholds = load_thresholds(args.thresholds)
|
|
68
|
+
failures = evaluate_thresholds(thresholds, results)
|
|
69
|
+
if failures:
|
|
70
|
+
print("Benchmark threshold failures:")
|
|
71
|
+
for failure in failures:
|
|
72
|
+
print(f"- {failure}")
|
|
73
|
+
raise SystemExit(1)
|
|
74
|
+
print(f"Benchmark thresholds passed using {args.thresholds}")
|
|
47
75
|
|
|
48
76
|
|
|
49
77
|
if __name__ == "__main__":
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import argparse
|
|
4
4
|
import importlib
|
|
5
5
|
import io
|
|
6
|
+
import json
|
|
6
7
|
import os
|
|
7
8
|
import platform
|
|
8
9
|
import statistics
|
|
@@ -794,6 +795,12 @@ def _render_report(
|
|
|
794
795
|
lines.append(f"- Processor: `{platform.processor() or 'unknown'}`")
|
|
795
796
|
lines.append(f"- Python: `{sys.version.split()[0]}`")
|
|
796
797
|
lines.append(f"- TensorStudio: `{ts.__version__}`")
|
|
798
|
+
with suppress(Exception):
|
|
799
|
+
perf_info = ts.performance_info()
|
|
800
|
+
lines.append(f"- TensorStudio threads: `{perf_info['num_threads']}`")
|
|
801
|
+
lines.append(f"- TensorStudio BLAS enabled: `{perf_info['blas_enabled']}`")
|
|
802
|
+
lines.append(f"- TensorStudio SIMD level: `{perf_info['simd_level']}`")
|
|
803
|
+
lines.append(f"- TensorStudio storage pool enabled: `{perf_info['storage_pool_enabled']}`")
|
|
797
804
|
lines.append(f"- NumPy: `{np.__version__}`")
|
|
798
805
|
for library in libraries:
|
|
799
806
|
if library.name in {"TensorStudio", "NumPy"}:
|
|
@@ -925,14 +932,55 @@ def _render_report(
|
|
|
925
932
|
return "\n".join(lines)
|
|
926
933
|
|
|
927
934
|
|
|
928
|
-
def
|
|
935
|
+
def run_benchmark_data(
|
|
936
|
+
sections: set[str],
|
|
937
|
+
) -> tuple[list[BenchmarkCase], list[Library], dict[str, Stats]]:
|
|
929
938
|
libraries = _load_libraries()
|
|
930
939
|
cases = _build_cases(sections)
|
|
931
940
|
results = _run_cases(cases, libraries)
|
|
932
|
-
|
|
941
|
+
return cases, libraries, results
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
def render_benchmark_report(
|
|
945
|
+
cases: list[BenchmarkCase],
|
|
946
|
+
libraries: list[Library],
|
|
947
|
+
results: dict[str, Stats],
|
|
948
|
+
) -> str:
|
|
949
|
+
return _render_report(cases, libraries, results)
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
def write_benchmark_report(report: str, output: Path | None) -> None:
|
|
933
953
|
if output is not None:
|
|
934
954
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
935
955
|
output.write_text(report, encoding="utf-8")
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
def load_thresholds(path: Path) -> dict[str, Any]:
|
|
959
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
def evaluate_thresholds(thresholds: dict[str, Any], results: dict[str, Stats]) -> list[str]:
|
|
963
|
+
failures: list[str] = []
|
|
964
|
+
for item in thresholds.get("cases", []):
|
|
965
|
+
category = str(item["category"])
|
|
966
|
+
operation = str(item["operation"])
|
|
967
|
+
shape = str(item["shape"])
|
|
968
|
+
max_ms = float(item["max_median_ms"])
|
|
969
|
+
key = f"{category}|{operation}|{shape}|TensorStudio"
|
|
970
|
+
stats = results.get(key)
|
|
971
|
+
label = f"{category}/{operation}/{shape}"
|
|
972
|
+
if stats is None:
|
|
973
|
+
failures.append(f"{label}: no TensorStudio benchmark result was recorded")
|
|
974
|
+
continue
|
|
975
|
+
if stats.median_ms > max_ms:
|
|
976
|
+
failures.append(f"{label}: median {stats.median_ms:.4f} ms exceeded {max_ms:.4f} ms")
|
|
977
|
+
return failures
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
def run_benchmarks(sections: set[str], output: Path | None) -> str:
|
|
981
|
+
cases, libraries, results = run_benchmark_data(sections)
|
|
982
|
+
report = _render_report(cases, libraries, results)
|
|
983
|
+
write_benchmark_report(report, output)
|
|
936
984
|
return report
|
|
937
985
|
|
|
938
986
|
|