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.
Files changed (187) hide show
  1. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/CHANGELOG.md +43 -0
  2. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/CMakeLists.txt +18 -1
  3. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/PKG-INFO +67 -28
  4. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/README.md +66 -27
  5. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmark_all.py +30 -2
  6. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/benchmark_report.py +50 -2
  7. tensorstudio-1.7.0/benchmarks/results.md +347 -0
  8. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_conv2d.md +39 -39
  9. tensorstudio-1.7.0/benchmarks/results_matmul.md +49 -0
  10. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_pooling.md +45 -45
  11. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_reductions.md +75 -75
  12. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/results_tensor_ops.md +309 -309
  13. tensorstudio-1.7.0/benchmarks/thresholds.json +49 -0
  14. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/autograd/coverage.md +9 -1
  15. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/api-reference.md +65 -0
  16. tensorstudio-1.7.0/docs/core/math-and-statistics.md +171 -0
  17. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/tensors.md +33 -1
  18. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/getting-started/quickstart.md +29 -2
  19. tensorstudio-1.7.0/docs/hardware/cpu-backend.md +84 -0
  20. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/hardware/linux.md +18 -0
  21. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/hardware/macos.md +15 -0
  22. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/hardware/windows.md +22 -0
  23. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/index.md +11 -8
  24. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/onnx.md +1 -1
  25. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/serialization.md +1 -1
  26. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/training.md +2 -1
  27. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/performance/benchmarks.md +21 -7
  28. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/performance/optimization.md +24 -6
  29. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/release/publishing.md +4 -4
  30. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/release/versioning.md +2 -2
  31. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/roadmap/milestones.md +3 -0
  32. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/roadmap/roadmap.md +31 -20
  33. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/ops.hpp +13 -0
  34. tensorstudio-1.7.0/include/tensorstudio/perf.hpp +34 -0
  35. tensorstudio-1.7.0/include/tensorstudio/random.hpp +36 -0
  36. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/storage.hpp +2 -0
  37. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/version.hpp +1 -1
  38. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/mkdocs.yml +1 -0
  39. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/pyproject.toml +1 -1
  40. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/_C.pyi +56 -1
  41. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/__init__.py +41 -0
  42. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/_version.py +1 -1
  43. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/math.py +87 -0
  44. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/functional.py +4 -5
  45. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/ops.py +60 -0
  46. tensorstudio-1.7.0/python/tensorstudio/performance.py +39 -0
  47. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/tensor.py +120 -0
  48. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_ops.cpp +51 -0
  49. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_tensor.cpp +148 -11
  50. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bindings.cpp +15 -0
  51. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/ops.cpp +613 -78
  52. tensorstudio-1.7.0/src/core/perf.cpp +250 -0
  53. tensorstudio-1.7.0/src/core/random.cpp +107 -0
  54. tensorstudio-1.7.0/src/core/storage.cpp +116 -0
  55. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_benchmark_report.py +26 -1
  56. tensorstudio-1.7.0/tests/test_core_math_expansion.py +156 -0
  57. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_import.py +1 -1
  58. tensorstudio-1.7.0/tests/test_performance.py +43 -0
  59. tensorstudio-1.5.1/benchmarks/results.md +0 -343
  60. tensorstudio-1.5.1/benchmarks/results_matmul.md +0 -45
  61. tensorstudio-1.5.1/docs/hardware/cpu-backend.md +0 -40
  62. tensorstudio-1.5.1/include/tensorstudio/random.hpp +0 -13
  63. tensorstudio-1.5.1/src/core/random.cpp +0 -54
  64. tensorstudio-1.5.1/src/core/storage.cpp +0 -29
  65. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.gitattributes +0 -0
  66. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/ci.yml +0 -0
  67. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/publish-testpypi.yml +0 -0
  68. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/publish.yml +0 -0
  69. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.github/workflows/wheels.yml +0 -0
  70. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.gitignore +0 -0
  71. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/.pre-commit-config.yaml +0 -0
  72. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/CONTRIBUTING.md +0 -0
  73. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/LICENSE +0 -0
  74. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/SECURITY.md +0 -0
  75. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/__init__.py +0 -0
  76. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_activations.py +0 -0
  77. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_autograd.py +0 -0
  78. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_conv2d.py +0 -0
  79. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_elementwise.py +0 -0
  80. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_matmul.py +0 -0
  81. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_pooling.py +0 -0
  82. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_reductions.py +0 -0
  83. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_tensor_ops.py +0 -0
  84. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/benchmarks/bench_training_loop.py +0 -0
  85. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/autograd/gradient-notes.md +0 -0
  86. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/autograd/overview.md +0 -0
  87. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/broadcasting.md +0 -0
  88. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/core/native-cpp-core.md +0 -0
  89. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/data/dataloader-patterns.md +0 -0
  90. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/data/datasets-and-dataloaders.md +0 -0
  91. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/data/tensor-datasets.md +0 -0
  92. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/development/contributing.md +0 -0
  93. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/development/cpp-first.md +0 -0
  94. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/getting-started/installation.md +0 -0
  95. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/getting-started/source-build.md +0 -0
  96. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/model-formats.md +0 -0
  97. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/numpy-interop.md +0 -0
  98. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/interchange/trusted-serialization.md +0 -0
  99. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/modules.md +0 -0
  100. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/optimizers.md +0 -0
  101. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/nn/overview.md +0 -0
  102. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/performance/profiling.md +0 -0
  103. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/project/checkpoints.md +0 -0
  104. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/project/project-layout.md +0 -0
  105. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/project/workflows.md +0 -0
  106. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/release/checklist.md +0 -0
  107. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/roadmap/priorities.md +0 -0
  108. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/vision/dataset-creation.md +0 -0
  109. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/docs/vision/overview.md +0 -0
  110. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/basic_tensor_ops.py +0 -0
  111. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/export_onnx.py +0 -0
  112. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/image_folder_classification.py +0 -0
  113. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/linear_regression.py +0 -0
  114. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/project_training.py +0 -0
  115. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/save_load_model.py +0 -0
  116. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/tiny_mlp.py +0 -0
  117. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/examples/vision_classifier.py +0 -0
  118. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/autograd.hpp +0 -0
  119. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/device.hpp +0 -0
  120. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/dtype.hpp +0 -0
  121. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/errors.hpp +0 -0
  122. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/module.hpp +0 -0
  123. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/optim.hpp +0 -0
  124. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/serialization.hpp +0 -0
  125. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/shape.hpp +0 -0
  126. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/include/tensorstudio/tensor.hpp +0 -0
  127. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/autograd.py +0 -0
  128. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/data/__init__.py +0 -0
  129. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/data/dataloader.py +0 -0
  130. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/data/dataset.py +0 -0
  131. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/dtypes.py +0 -0
  132. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/errors.py +0 -0
  133. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/grad_mode.py +0 -0
  134. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/interchange/__init__.py +0 -0
  135. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/interchange/onnx.py +0 -0
  136. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/__init__.py +0 -0
  137. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/losses.py +0 -0
  138. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/nn/modules.py +0 -0
  139. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/__init__.py +0 -0
  140. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/adam.py +0 -0
  141. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/adamw.py +0 -0
  142. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/lr_scheduler.py +0 -0
  143. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/sgd.py +0 -0
  144. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/optim/utils.py +0 -0
  145. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/__init__.py +0 -0
  146. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/checkpoint.py +0 -0
  147. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/config.py +0 -0
  148. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/project/trainer.py +0 -0
  149. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/py.typed +0 -0
  150. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/serialization.py +0 -0
  151. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/typing.py +0 -0
  152. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/__init__.py +0 -0
  153. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/datasets.py +0 -0
  154. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/io.py +0 -0
  155. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/metrics.py +0 -0
  156. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/models.py +0 -0
  157. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/transforms.py +0 -0
  158. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/python/tensorstudio/vision/visualization.py +0 -0
  159. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_autograd.cpp +0 -0
  160. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_nn.cpp +0 -0
  161. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bind_optim.cpp +0 -0
  162. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/bindings/bindings.hpp +0 -0
  163. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/autograd.cpp +0 -0
  164. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/device.cpp +0 -0
  165. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/dtype.cpp +0 -0
  166. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/errors.cpp +0 -0
  167. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/module.cpp +0 -0
  168. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/optim.cpp +0 -0
  169. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/serialization.cpp +0 -0
  170. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/shape.cpp +0 -0
  171. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/src/core/tensor.cpp +0 -0
  172. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/test_all.py +0 -0
  173. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_autograd.py +0 -0
  174. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_broadcasting.py +0 -0
  175. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_data.py +0 -0
  176. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_errors.py +0 -0
  177. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_indexing.py +0 -0
  178. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_interchange.py +0 -0
  179. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_nn.py +0 -0
  180. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_numpy_interop.py +0 -0
  181. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_ops.py +0 -0
  182. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_optim.py +0 -0
  183. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_project.py +0 -0
  184. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_serialization.py +0 -0
  185. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_tensor.py +0 -0
  186. {tensorstudio-1.5.1 → tensorstudio-1.7.0}/tests/test_views.py +0 -0
  187. {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.5.1 LANGUAGES CXX)
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.5.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.5.1` is a CPU-only stable API foundation. It is eager-only,
75
- intentionally small, and not a replacement for mature ML frameworks.
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
- Higher-level helpers live in `tensorstudio.math`:
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([[1.0, 2.0], [3.0, 4.0]])
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
- On one Windows CPython 3.10 development run reporting `1.2.0`, TensorStudio
348
- beat NumPy on 26 small operation benchmark cases and lost on 77
349
- NumPy-comparable cases. Against PyTorch CPU `2.12.1+cpu`, TensorStudio won 75
350
- local cases and lost 33. The strongest local wins were small eager operations,
351
- small contiguous axis reductions, and the simple NumPy convolution/pooling
352
- references where framework dispatch or Python loops dominate; larger matrix
353
- multiplication, PyTorch convolution and pooling, larger axis reductions, larger
354
- transcendental activations, and larger autograd workloads remain faster in
355
- PyTorch and NumPy.
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 | PyTorch CPU | TS vs NumPy | TS vs PyTorch |
398
+ | operation | shape | TensorStudio | NumPy | JAX CPU dispatch | TS vs NumPy | TS vs JAX |
362
399
  |---|---:|---:|---:|---:|---:|---:|
363
- | `sigmoid` | `(32,)` | 0.0017 ms | 0.0038 ms | 0.0614 ms | 2.1691x | 35.3154x |
364
- | `mean` | `(32,)` | 0.0029 ms | 0.0131 ms | 0.0186 ms | 4.5638x | 6.4709x |
365
- | `sum_axis1` | `(16, 16)` | 0.0027 ms | 0.0029 ms | 0.0085 ms | 1.0894x | 3.1408x |
366
- | `chain_relu` | `(128,)` | 0.0112 ms | 0.0051 ms | 0.0726 ms | 0.4575x | 6.4533x |
367
- | `matmul` | `(256, 256)` | 4.4121 ms | 0.3779 ms | 0.1669 ms | 0.0856x | 0.0378x |
368
- | `conv2d_3x3_padding1` | `(1, 1, 8, 8)` | 0.2374 ms | 1.7112 ms | 0.0186 ms | 7.2091x | 0.0784x |
369
- | `max_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0237 ms | 0.2764 ms | 0.0082 ms | 11.6685x | 0.3462x |
370
- | `avg_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0198 ms | 0.7431 ms | 0.0073 ms | 37.4930x | 0.3662x |
371
- | `elementwise_backward` | `(1024,)` | 3.0196 ms | n/a | 0.2254 ms | n/a | 0.0746x |
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
- - No BLAS-backed matrix multiplication yet.
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
- - Improved memory allocator
499
- - SIMD kernels
500
- - Multithreaded ops
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.5.1` is a CPU-only stable API foundation. It is eager-only,
11
- intentionally small, and not a replacement for mature ML frameworks.
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
- Higher-level helpers live in `tensorstudio.math`:
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([[1.0, 2.0], [3.0, 4.0]])
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
- On one Windows CPython 3.10 development run reporting `1.2.0`, TensorStudio
284
- beat NumPy on 26 small operation benchmark cases and lost on 77
285
- NumPy-comparable cases. Against PyTorch CPU `2.12.1+cpu`, TensorStudio won 75
286
- local cases and lost 33. The strongest local wins were small eager operations,
287
- small contiguous axis reductions, and the simple NumPy convolution/pooling
288
- references where framework dispatch or Python loops dominate; larger matrix
289
- multiplication, PyTorch convolution and pooling, larger axis reductions, larger
290
- transcendental activations, and larger autograd workloads remain faster in
291
- PyTorch and NumPy.
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 | PyTorch CPU | TS vs NumPy | TS vs PyTorch |
334
+ | operation | shape | TensorStudio | NumPy | JAX CPU dispatch | TS vs NumPy | TS vs JAX |
298
335
  |---|---:|---:|---:|---:|---:|---:|
299
- | `sigmoid` | `(32,)` | 0.0017 ms | 0.0038 ms | 0.0614 ms | 2.1691x | 35.3154x |
300
- | `mean` | `(32,)` | 0.0029 ms | 0.0131 ms | 0.0186 ms | 4.5638x | 6.4709x |
301
- | `sum_axis1` | `(16, 16)` | 0.0027 ms | 0.0029 ms | 0.0085 ms | 1.0894x | 3.1408x |
302
- | `chain_relu` | `(128,)` | 0.0112 ms | 0.0051 ms | 0.0726 ms | 0.4575x | 6.4533x |
303
- | `matmul` | `(256, 256)` | 4.4121 ms | 0.3779 ms | 0.1669 ms | 0.0856x | 0.0378x |
304
- | `conv2d_3x3_padding1` | `(1, 1, 8, 8)` | 0.2374 ms | 1.7112 ms | 0.0186 ms | 7.2091x | 0.0784x |
305
- | `max_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0237 ms | 0.2764 ms | 0.0082 ms | 11.6685x | 0.3462x |
306
- | `avg_pool2d_2x2` | `(1, 1, 16, 16)` | 0.0198 ms | 0.7431 ms | 0.0073 ms | 37.4930x | 0.3662x |
307
- | `elementwise_backward` | `(1024,)` | 3.0196 ms | n/a | 0.2254 ms | n/a | 0.0746x |
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
- - No BLAS-backed matrix multiplication yet.
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
- - Improved memory allocator
435
- - SIMD kernels
436
- - Multithreaded ops
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 run_benchmarks
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
- report = run_benchmarks(selected_sections, args.output)
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 run_benchmarks(sections: set[str], output: Path | None) -> str:
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
- report = _render_report(cases, libraries, results)
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