tack-core 0.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.
- tack_core-0.7.0/.gitignore +25 -0
- tack_core-0.7.0/LICENSE +29 -0
- tack_core-0.7.0/PKG-INFO +116 -0
- tack_core-0.7.0/README.md +70 -0
- tack_core-0.7.0/examples/01_hello_tack.py +57 -0
- tack_core-0.7.0/examples/02_math_builtins.py +54 -0
- tack_core-0.7.0/examples/03_scalar_args.py +56 -0
- tack_core-0.7.0/examples/04_control_flow.py +102 -0
- tack_core-0.7.0/examples/05_ndindex.py +78 -0
- tack_core-0.7.0/examples/06_device_functions.py +78 -0
- tack_core-0.7.0/examples/07_atomics.py +91 -0
- tack_core-0.7.0/examples/08_reductions.py +45 -0
- tack_core-0.7.0/examples/09_shared_memory.py +97 -0
- tack_core-0.7.0/examples/10_vectors.py +129 -0
- tack_core-0.7.0/examples/11_templates.py +94 -0
- tack_core-0.7.0/examples/12_mandelbrot.py +90 -0
- tack_core-0.7.0/examples/13_nbody.py +105 -0
- tack_core-0.7.0/examples/14_jacobi_solver.py +91 -0
- tack_core-0.7.0/examples/15_matmul.py +68 -0
- tack_core-0.7.0/examples/16_game_of_life.py +122 -0
- tack_core-0.7.0/examples/17_heat_equation.py +114 -0
- tack_core-0.7.0/examples/18_wave_equation.py +104 -0
- tack_core-0.7.0/examples/19_image_processing.py +163 -0
- tack_core-0.7.0/examples/20_multi_backend.py +111 -0
- tack_core-0.7.0/examples/21_array_abstraction.py +187 -0
- tack_core-0.7.0/examples/23_tuple_arrays.py +349 -0
- tack_core-0.7.0/examples/24_point_coordinates.py +386 -0
- tack_core-0.7.0/examples/29_volume_render.py +532 -0
- tack_core-0.7.0/examples/30_scalar_packing.py +79 -0
- tack_core-0.7.0/examples/31_dawn_interop.py +203 -0
- tack_core-0.7.0/examples/40_statistics.py +147 -0
- tack_core-0.7.0/examples/41_inspect.py +71 -0
- tack_core-0.7.0/examples/validate_all.py +457 -0
- tack_core-0.7.0/pyproject.toml +86 -0
- tack_core-0.7.0/src/tack/__init__.py +294 -0
- tack_core-0.7.0/src/tack/algorithms/__init__.py +60 -0
- tack_core-0.7.0/src/tack/algorithms/copy.py +49 -0
- tack_core-0.7.0/src/tack/algorithms/scan.py +292 -0
- tack_core-0.7.0/src/tack/algorithms/segmented.py +612 -0
- tack_core-0.7.0/src/tack/algorithms/sort.py +626 -0
- tack_core-0.7.0/src/tack/algorithms/stats.py +282 -0
- tack_core-0.7.0/src/tack/arrays.py +820 -0
- tack_core-0.7.0/src/tack/cache.py +90 -0
- tack_core-0.7.0/src/tack/codegen/__init__.py +2 -0
- tack_core-0.7.0/src/tack/codegen/atomics.py +40 -0
- tack_core-0.7.0/src/tack/codegen/bounds.py +63 -0
- tack_core-0.7.0/src/tack/codegen/c_family.py +219 -0
- tack_core-0.7.0/src/tack/codegen/cuda_gen.py +767 -0
- tack_core-0.7.0/src/tack/codegen/float_division.py +66 -0
- tack_core-0.7.0/src/tack/codegen/hip_gen.py +55 -0
- tack_core-0.7.0/src/tack/codegen/identifiers.py +58 -0
- tack_core-0.7.0/src/tack/codegen/integer_division.py +47 -0
- tack_core-0.7.0/src/tack/codegen/integer_ops.py +138 -0
- tack_core-0.7.0/src/tack/codegen/llvm_gen.py +1516 -0
- tack_core-0.7.0/src/tack/codegen/msl_gen.py +746 -0
- tack_core-0.7.0/src/tack/codegen/opencl_gen.py +579 -0
- tack_core-0.7.0/src/tack/codegen/reductions.py +109 -0
- tack_core-0.7.0/src/tack/codegen/tables.py +53 -0
- tack_core-0.7.0/src/tack/codegen/warp_gen.py +761 -0
- tack_core-0.7.0/src/tack/communication/__init__.py +43 -0
- tack_core-0.7.0/src/tack/communication/_blocks.py +207 -0
- tack_core-0.7.0/src/tack/communication/_kernels.py +83 -0
- tack_core-0.7.0/src/tack/communication/_plan.py +136 -0
- tack_core-0.7.0/src/tack/communication/_route.py +186 -0
- tack_core-0.7.0/src/tack/communication/_sort.py +170 -0
- tack_core-0.7.0/src/tack/communication/_world.py +165 -0
- tack_core-0.7.0/src/tack/lang/__init__.py +2 -0
- tack_core-0.7.0/src/tack/lang/array.py +1338 -0
- tack_core-0.7.0/src/tack/lang/ast_copy.py +35 -0
- tack_core-0.7.0/src/tack/lang/ast_transform.py +1147 -0
- tack_core-0.7.0/src/tack/lang/atomic_support.py +85 -0
- tack_core-0.7.0/src/tack/lang/call_bindings.py +102 -0
- tack_core-0.7.0/src/tack/lang/constant.py +227 -0
- tack_core-0.7.0/src/tack/lang/device_class.py +32 -0
- tack_core-0.7.0/src/tack/lang/dlpack.py +651 -0
- tack_core-0.7.0/src/tack/lang/func.py +114 -0
- tack_core-0.7.0/src/tack/lang/inspect_kernel.py +228 -0
- tack_core-0.7.0/src/tack/lang/ir.py +530 -0
- tack_core-0.7.0/src/tack/lang/ir_bounds.py +154 -0
- tack_core-0.7.0/src/tack/lang/ir_names.py +47 -0
- tack_core-0.7.0/src/tack/lang/ir_optimize.py +224 -0
- tack_core-0.7.0/src/tack/lang/ir_pack_scalars.py +105 -0
- tack_core-0.7.0/src/tack/lang/ir_resolve.py +149 -0
- tack_core-0.7.0/src/tack/lang/ir_traversal.py +189 -0
- tack_core-0.7.0/src/tack/lang/ir_type_annotate.py +514 -0
- tack_core-0.7.0/src/tack/lang/ir_verify.py +280 -0
- tack_core-0.7.0/src/tack/lang/kernel.py +379 -0
- tack_core-0.7.0/src/tack/lang/lowering/__init__.py +25 -0
- tack_core-0.7.0/src/tack/lang/lowering/arrays.py +299 -0
- tack_core-0.7.0/src/tack/lang/lowering/bounds.py +107 -0
- tack_core-0.7.0/src/tack/lang/lowering/checks.py +190 -0
- tack_core-0.7.0/src/tack/lang/lowering/inlining.py +344 -0
- tack_core-0.7.0/src/tack/lang/lowering/local_arrays.py +135 -0
- tack_core-0.7.0/src/tack/lang/lowering/loops.py +387 -0
- tack_core-0.7.0/src/tack/lang/lowering/values.py +86 -0
- tack_core-0.7.0/src/tack/lang/lowering/vectors.py +664 -0
- tack_core-0.7.0/src/tack/lang/parallel_dims.py +90 -0
- tack_core-0.7.0/src/tack/lang/source_validation.py +185 -0
- tack_core-0.7.0/src/tack/lang/template_rewrite.py +1176 -0
- tack_core-0.7.0/src/tack/lang/type_inference.py +144 -0
- tack_core-0.7.0/src/tack/lang/types.py +249 -0
- tack_core-0.7.0/src/tack/lang/workgroup_participation.py +208 -0
- tack_core-0.7.0/src/tack/lang/workgroup_support.py +51 -0
- tack_core-0.7.0/src/tack/math.py +93 -0
- tack_core-0.7.0/src/tack/py.typed +0 -0
- tack_core-0.7.0/src/tack/random.py +137 -0
- tack_core-0.7.0/src/tack/runtime/__init__.py +2 -0
- tack_core-0.7.0/src/tack/runtime/aio.py +115 -0
- tack_core-0.7.0/src/tack/runtime/backend.py +287 -0
- tack_core-0.7.0/src/tack/runtime/buffer_cache.py +90 -0
- tack_core-0.7.0/src/tack/runtime/cpu.py +2329 -0
- tack_core-0.7.0/src/tack/runtime/cpu_pool.py +804 -0
- tack_core-0.7.0/src/tack/runtime/cuda_backend.py +1411 -0
- tack_core-0.7.0/src/tack/runtime/debug_bounds.py +122 -0
- tack_core-0.7.0/src/tack/runtime/device_fill.py +68 -0
- tack_core-0.7.0/src/tack/runtime/disk_cache.py +1001 -0
- tack_core-0.7.0/src/tack/runtime/dispatch.py +454 -0
- tack_core-0.7.0/src/tack/runtime/gpu_backend.py +184 -0
- tack_core-0.7.0/src/tack/runtime/hip_backend.py +1163 -0
- tack_core-0.7.0/src/tack/runtime/kernel_utils.py +1518 -0
- tack_core-0.7.0/src/tack/runtime/level_zero_backend.py +1997 -0
- tack_core-0.7.0/src/tack/runtime/metal.py +890 -0
- tack_core-0.7.0/src/tack/runtime/nvrtc_version.py +28 -0
- tack_core-0.7.0/src/tack/runtime/reductions.py +38 -0
- tack_core-0.7.0/src/tack/runtime/warp_backend.py +266 -0
- tack_core-0.7.0/tests/_communication_cases.py +246 -0
- tack_core-0.7.0/tests/_communication_mpi.py +78 -0
- tack_core-0.7.0/tests/_warp_default.py +43 -0
- tack_core-0.7.0/tests/compiler_tools.py +164 -0
- tack_core-0.7.0/tests/test_array_api.py +258 -0
- tack_core-0.7.0/tests/test_array_constructors.py +267 -0
- tack_core-0.7.0/tests/test_array_shape.py +346 -0
- tack_core-0.7.0/tests/test_array_updates_in_loops.py +254 -0
- tack_core-0.7.0/tests/test_array_utils.py +532 -0
- tack_core-0.7.0/tests/test_arrays_protocol.py +260 -0
- tack_core-0.7.0/tests/test_ast_transform.py +519 -0
- tack_core-0.7.0/tests/test_asyncio.py +338 -0
- tack_core-0.7.0/tests/test_atomic_contract.py +485 -0
- tack_core-0.7.0/tests/test_atomic_results.py +124 -0
- tack_core-0.7.0/tests/test_backend_contract.py +296 -0
- tack_core-0.7.0/tests/test_backend_isolation.py +96 -0
- tack_core-0.7.0/tests/test_block_reduce.py +86 -0
- tack_core-0.7.0/tests/test_buffer_cache.py +57 -0
- tack_core-0.7.0/tests/test_cleanup.py +276 -0
- tack_core-0.7.0/tests/test_communication.py +428 -0
- tack_core-0.7.0/tests/test_compiler_contract.py +478 -0
- tack_core-0.7.0/tests/test_compiler_tools.py +210 -0
- tack_core-0.7.0/tests/test_concurrent_dispatch.py +459 -0
- tack_core-0.7.0/tests/test_constant.py +280 -0
- tack_core-0.7.0/tests/test_constant_tables.py +195 -0
- tack_core-0.7.0/tests/test_cpu_fill.py +228 -0
- tack_core-0.7.0/tests/test_cpu_jit.py +388 -0
- tack_core-0.7.0/tests/test_cpu_pool.py +441 -0
- tack_core-0.7.0/tests/test_cpu_threading.py +1718 -0
- tack_core-0.7.0/tests/test_cuda.py +729 -0
- tack_core-0.7.0/tests/test_cuda_async.py +265 -0
- tack_core-0.7.0/tests/test_cuda_gen.py +288 -0
- tack_core-0.7.0/tests/test_debug_bounds.py +417 -0
- tack_core-0.7.0/tests/test_default_float.py +107 -0
- tack_core-0.7.0/tests/test_devices.py +378 -0
- tack_core-0.7.0/tests/test_differential.py +272 -0
- tack_core-0.7.0/tests/test_disjoint_fields.py +284 -0
- tack_core-0.7.0/tests/test_disk_cache.py +767 -0
- tack_core-0.7.0/tests/test_dispatch_fast_path.py +236 -0
- tack_core-0.7.0/tests/test_dispatch_signature_property.py +221 -0
- tack_core-0.7.0/tests/test_dispatch_types.py +156 -0
- tack_core-0.7.0/tests/test_division_and_power.py +342 -0
- tack_core-0.7.0/tests/test_dlpack.py +652 -0
- tack_core-0.7.0/tests/test_error_messages.py +212 -0
- tack_core-0.7.0/tests/test_error_reporting.py +74 -0
- tack_core-0.7.0/tests/test_examples.py +99 -0
- tack_core-0.7.0/tests/test_explicit_casts.py +223 -0
- tack_core-0.7.0/tests/test_f64_refused.py +106 -0
- tack_core-0.7.0/tests/test_float_division.py +326 -0
- tack_core-0.7.0/tests/test_float_literals.py +359 -0
- tack_core-0.7.0/tests/test_float_semantics.py +502 -0
- tack_core-0.7.0/tests/test_func_bindings.py +270 -0
- tack_core-0.7.0/tests/test_gpu_dispatch_paths.py +399 -0
- tack_core-0.7.0/tests/test_gpu_identifiers.py +336 -0
- tack_core-0.7.0/tests/test_hip.py +668 -0
- tack_core-0.7.0/tests/test_hip_async.py +338 -0
- tack_core-0.7.0/tests/test_hip_gen.py +171 -0
- tack_core-0.7.0/tests/test_indexable.py +318 -0
- tack_core-0.7.0/tests/test_inspect.py +166 -0
- tack_core-0.7.0/tests/test_integer_division.py +214 -0
- tack_core-0.7.0/tests/test_integer_expression_differential.py +571 -0
- tack_core-0.7.0/tests/test_integer_semantics.py +465 -0
- tack_core-0.7.0/tests/test_ir_clone.py +171 -0
- tack_core-0.7.0/tests/test_ir_optimize.py +148 -0
- tack_core-0.7.0/tests/test_ir_traversal.py +139 -0
- tack_core-0.7.0/tests/test_ir_verify.py +335 -0
- tack_core-0.7.0/tests/test_kernel_cache.py +108 -0
- tack_core-0.7.0/tests/test_kernel_results.py +117 -0
- tack_core-0.7.0/tests/test_launch_limits.py +93 -0
- tack_core-0.7.0/tests/test_level_zero_async.py +354 -0
- tack_core-0.7.0/tests/test_level_zero_buffers.py +61 -0
- tack_core-0.7.0/tests/test_level_zero_context.py +102 -0
- tack_core-0.7.0/tests/test_llvm_gen.py +242 -0
- tack_core-0.7.0/tests/test_local_array.py +251 -0
- tack_core-0.7.0/tests/test_local_var_types.py +140 -0
- tack_core-0.7.0/tests/test_math_helpers.py +78 -0
- tack_core-0.7.0/tests/test_matrix.py +319 -0
- tack_core-0.7.0/tests/test_metal.py +519 -0
- tack_core-0.7.0/tests/test_msl_gen.py +264 -0
- tack_core-0.7.0/tests/test_multi_device.py +294 -0
- tack_core-0.7.0/tests/test_multi_device_switching.py +689 -0
- tack_core-0.7.0/tests/test_nested_templates.py +227 -0
- tack_core-0.7.0/tests/test_new_features.py +1780 -0
- tack_core-0.7.0/tests/test_numa.py +395 -0
- tack_core-0.7.0/tests/test_nvrtc_version.py +17 -0
- tack_core-0.7.0/tests/test_opencl_compilation.py +388 -0
- tack_core-0.7.0/tests/test_opencl_gen.py +657 -0
- tack_core-0.7.0/tests/test_out_of_memory.py +91 -0
- tack_core-0.7.0/tests/test_outside_parallel_loop.py +210 -0
- tack_core-0.7.0/tests/test_package_surface.py +65 -0
- tack_core-0.7.0/tests/test_parallel_dims.py +367 -0
- tack_core-0.7.0/tests/test_promotion_and_safety.py +165 -0
- tack_core-0.7.0/tests/test_random.py +74 -0
- tack_core-0.7.0/tests/test_reduction_semantics.py +347 -0
- tack_core-0.7.0/tests/test_scalar_matching.py +159 -0
- tack_core-0.7.0/tests/test_scalar_packing.py +105 -0
- tack_core-0.7.0/tests/test_segmented.py +188 -0
- tack_core-0.7.0/tests/test_shared_like.py +139 -0
- tack_core-0.7.0/tests/test_small_int_types.py +225 -0
- tack_core-0.7.0/tests/test_soa.py +408 -0
- tack_core-0.7.0/tests/test_sort.py +378 -0
- tack_core-0.7.0/tests/test_source_validation.py +395 -0
- tack_core-0.7.0/tests/test_stats.py +345 -0
- tack_core-0.7.0/tests/test_template_iteration.py +193 -0
- tack_core-0.7.0/tests/test_templates.py +607 -0
- tack_core-0.7.0/tests/test_texture_inline.py +113 -0
- tack_core-0.7.0/tests/test_texture_snapshot.py +150 -0
- tack_core-0.7.0/tests/test_threading_benchmark.py +273 -0
- tack_core-0.7.0/tests/test_type_annotate.py +117 -0
- tack_core-0.7.0/tests/test_type_annotate_expr.py +530 -0
- tack_core-0.7.0/tests/test_type_inference.py +60 -0
- tack_core-0.7.0/tests/test_validation_harness.py +190 -0
- tack_core-0.7.0/tests/test_value_constructors.py +102 -0
- tack_core-0.7.0/tests/test_variable_length_loop.py +153 -0
- tack_core-0.7.0/tests/test_variant_cache.py +367 -0
- tack_core-0.7.0/tests/test_vector_add.py +46 -0
- tack_core-0.7.0/tests/test_vector_comparisons.py +154 -0
- tack_core-0.7.0/tests/test_warp.py +459 -0
- tack_core-0.7.0/tests/test_workgroup_contract.py +193 -0
- tack_core-0.7.0/tests/test_workgroup_participation.py +446 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Generated images and example output
|
|
13
|
+
results/
|
|
14
|
+
*.npy
|
|
15
|
+
*.vtu
|
|
16
|
+
|
|
17
|
+
# Claude Code local config
|
|
18
|
+
.claude/
|
|
19
|
+
|
|
20
|
+
# Test artifacts
|
|
21
|
+
.coverage
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
|
|
24
|
+
# MkDocs build output
|
|
25
|
+
site/
|
tack_core-0.7.0/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Kitware, Inc.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
tack_core-0.7.0/PKG-INFO
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: tack-core
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Tack — GPU compute framework (core)
|
|
5
|
+
Project-URL: Homepage, https://github.com/Kitware/tack
|
|
6
|
+
Project-URL: Repository, https://github.com/Kitware/tack
|
|
7
|
+
Project-URL: Documentation, https://kitware.github.io/tack/
|
|
8
|
+
Project-URL: Issues, https://github.com/Kitware/tack/issues
|
|
9
|
+
Author: Kitware, Inc.
|
|
10
|
+
License-Expression: BSD-3-Clause
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: compute,cuda,gpu,hip,jit,kernel,metal,visualization
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Classifier: Topic :: Software Development :: Compilers
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: numpy
|
|
23
|
+
Provides-Extra: all
|
|
24
|
+
Requires-Dist: cuda-python>=13.2.0; extra == 'all'
|
|
25
|
+
Requires-Dist: hip-python>=7.0; (sys_platform == 'linux' and platform_machine == 'x86_64') and extra == 'all'
|
|
26
|
+
Requires-Dist: llvmlite; extra == 'all'
|
|
27
|
+
Requires-Dist: pyobjc-framework-metal; extra == 'all'
|
|
28
|
+
Requires-Dist: pyobjc-framework-metalkit; extra == 'all'
|
|
29
|
+
Provides-Extra: cpu
|
|
30
|
+
Requires-Dist: llvmlite; extra == 'cpu'
|
|
31
|
+
Provides-Extra: cuda
|
|
32
|
+
Requires-Dist: cuda-python>=13.2.0; extra == 'cuda'
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
35
|
+
Provides-Extra: hip
|
|
36
|
+
Requires-Dist: hip-python>=7.0; (sys_platform == 'linux' and platform_machine == 'x86_64') and extra == 'hip'
|
|
37
|
+
Provides-Extra: level-zero
|
|
38
|
+
Provides-Extra: metal
|
|
39
|
+
Requires-Dist: pyobjc-framework-metal; extra == 'metal'
|
|
40
|
+
Requires-Dist: pyobjc-framework-metalkit; extra == 'metal'
|
|
41
|
+
Provides-Extra: mpi
|
|
42
|
+
Requires-Dist: mpi4py>=4.0; extra == 'mpi'
|
|
43
|
+
Provides-Extra: warp
|
|
44
|
+
Requires-Dist: warp-lang>=1.18; (sys_platform != 'darwin' or platform_machine == 'arm64') and extra == 'warp'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# tack-core
|
|
48
|
+
|
|
49
|
+
Kernels, arrays, types, IR, codegen and backends for [Tack](https://github.com/Kitware/tack) —
|
|
50
|
+
a Python-first GPU compute framework.
|
|
51
|
+
|
|
52
|
+
Write compute kernels as decorated Python functions; they are JIT-compiled at first call (and
|
|
53
|
+
kept in a disk cache, so a later process loads them instead) and dispatched to whichever backend
|
|
54
|
+
is active. The same kernel source runs on five backends, within
|
|
55
|
+
each backend's capabilities (for example, Metal has no `f64` and the CPU has no workgroup
|
|
56
|
+
primitives).
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
import tack, numpy as np
|
|
60
|
+
tack.set_default_device("cpu") # or metal, cuda, hip, level_zero
|
|
61
|
+
|
|
62
|
+
@tack.kernel
|
|
63
|
+
def vector_add(x, y, out):
|
|
64
|
+
for i in range(x.shape[0]): # outermost loop → thread parallelism
|
|
65
|
+
out[i] = x[i] + y[i]
|
|
66
|
+
|
|
67
|
+
x = tack.empty((1024,)) # f32 unless a dtype is given
|
|
68
|
+
y = tack.empty((1024,))
|
|
69
|
+
out = tack.empty((1024,))
|
|
70
|
+
tack.copyto(x, np.arange(1024, dtype=np.float32))
|
|
71
|
+
tack.copyto(y, np.ones(1024, dtype=np.float32))
|
|
72
|
+
|
|
73
|
+
vector_add(x, y, out)
|
|
74
|
+
print(out.numpy())
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Install
|
|
78
|
+
|
|
79
|
+
Pick the extras for your hardware. Keep `cpu` beside a GPU's extra: without it
|
|
80
|
+
the CPU, the default device, cannot run kernels.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install "tack-core[cpu]" # LLVM JIT via llvmlite
|
|
84
|
+
pip install "tack-core[cpu,metal]" # Apple silicon
|
|
85
|
+
pip install "tack-core[cpu,cuda]" # NVIDIA
|
|
86
|
+
pip install "tack-core[cpu,hip]" # AMD, with ROCm (hip-python: Linux x86-64)
|
|
87
|
+
pip install "tack-core[cpu]" # Intel: Level Zero is the system's runtime, no extra
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Python 3.11 or newer. Tack is pure Python and compiles kernels when they are
|
|
91
|
+
first called.
|
|
92
|
+
|
|
93
|
+
## Backends
|
|
94
|
+
|
|
95
|
+
| Backend | Codegen | Runtime compilation |
|
|
96
|
+
|---------|---------|---------------------|
|
|
97
|
+
| CPU | LLVM IR | llvmlite JIT |
|
|
98
|
+
| Metal | MSL | Metal API |
|
|
99
|
+
| CUDA | CUDA C | NVRTC → PTX |
|
|
100
|
+
| HIP | HIP C | hipRTC |
|
|
101
|
+
| Level Zero | OpenCL C | libocloc → SPIR-V |
|
|
102
|
+
|
|
103
|
+
## Related packages
|
|
104
|
+
|
|
105
|
+
- `tack-vis`: `tack.dataset`, with meshes, fields and visualization algorithms,
|
|
106
|
+
and the VTK and MFEM interop. It is not on PyPI; install it from the
|
|
107
|
+
repository, at the tag of the `tack-core` release you have, for example:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install "tack-vis @ git+https://github.com/Kitware/tack@v0.7.0#subdirectory=packages/tack-vis"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Full documentation, examples and the kernel-language reference are in the
|
|
114
|
+
[repository](https://github.com/Kitware/tack).
|
|
115
|
+
|
|
116
|
+
BSD 3-Clause licensed.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# tack-core
|
|
2
|
+
|
|
3
|
+
Kernels, arrays, types, IR, codegen and backends for [Tack](https://github.com/Kitware/tack) —
|
|
4
|
+
a Python-first GPU compute framework.
|
|
5
|
+
|
|
6
|
+
Write compute kernels as decorated Python functions; they are JIT-compiled at first call (and
|
|
7
|
+
kept in a disk cache, so a later process loads them instead) and dispatched to whichever backend
|
|
8
|
+
is active. The same kernel source runs on five backends, within
|
|
9
|
+
each backend's capabilities (for example, Metal has no `f64` and the CPU has no workgroup
|
|
10
|
+
primitives).
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
import tack, numpy as np
|
|
14
|
+
tack.set_default_device("cpu") # or metal, cuda, hip, level_zero
|
|
15
|
+
|
|
16
|
+
@tack.kernel
|
|
17
|
+
def vector_add(x, y, out):
|
|
18
|
+
for i in range(x.shape[0]): # outermost loop → thread parallelism
|
|
19
|
+
out[i] = x[i] + y[i]
|
|
20
|
+
|
|
21
|
+
x = tack.empty((1024,)) # f32 unless a dtype is given
|
|
22
|
+
y = tack.empty((1024,))
|
|
23
|
+
out = tack.empty((1024,))
|
|
24
|
+
tack.copyto(x, np.arange(1024, dtype=np.float32))
|
|
25
|
+
tack.copyto(y, np.ones(1024, dtype=np.float32))
|
|
26
|
+
|
|
27
|
+
vector_add(x, y, out)
|
|
28
|
+
print(out.numpy())
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
Pick the extras for your hardware. Keep `cpu` beside a GPU's extra: without it
|
|
34
|
+
the CPU, the default device, cannot run kernels.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install "tack-core[cpu]" # LLVM JIT via llvmlite
|
|
38
|
+
pip install "tack-core[cpu,metal]" # Apple silicon
|
|
39
|
+
pip install "tack-core[cpu,cuda]" # NVIDIA
|
|
40
|
+
pip install "tack-core[cpu,hip]" # AMD, with ROCm (hip-python: Linux x86-64)
|
|
41
|
+
pip install "tack-core[cpu]" # Intel: Level Zero is the system's runtime, no extra
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Python 3.11 or newer. Tack is pure Python and compiles kernels when they are
|
|
45
|
+
first called.
|
|
46
|
+
|
|
47
|
+
## Backends
|
|
48
|
+
|
|
49
|
+
| Backend | Codegen | Runtime compilation |
|
|
50
|
+
|---------|---------|---------------------|
|
|
51
|
+
| CPU | LLVM IR | llvmlite JIT |
|
|
52
|
+
| Metal | MSL | Metal API |
|
|
53
|
+
| CUDA | CUDA C | NVRTC → PTX |
|
|
54
|
+
| HIP | HIP C | hipRTC |
|
|
55
|
+
| Level Zero | OpenCL C | libocloc → SPIR-V |
|
|
56
|
+
|
|
57
|
+
## Related packages
|
|
58
|
+
|
|
59
|
+
- `tack-vis`: `tack.dataset`, with meshes, fields and visualization algorithms,
|
|
60
|
+
and the VTK and MFEM interop. It is not on PyPI; install it from the
|
|
61
|
+
repository, at the tag of the `tack-core` release you have, for example:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install "tack-vis @ git+https://github.com/Kitware/tack@v0.7.0#subdirectory=packages/tack-vis"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Full documentation, examples and the kernel-language reference are in the
|
|
68
|
+
[repository](https://github.com/Kitware/tack).
|
|
69
|
+
|
|
70
|
+
BSD 3-Clause licensed.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
"""01 -- Hello Tack: your first kernel.
|
|
5
|
+
|
|
6
|
+
This is the simplest possible Tack program. It creates two arrays,
|
|
7
|
+
adds them element-wise on the GPU (or CPU), and checks the result.
|
|
8
|
+
|
|
9
|
+
Key concepts:
|
|
10
|
+
- tack.set_default_device() -- choose a device (cpu, metal, cuda, hip)
|
|
11
|
+
- tack.empty() -- allocate a device array
|
|
12
|
+
- @tack.kernel -- mark a function for GPU compilation
|
|
13
|
+
- from_numpy / to_numpy -- move data between host and device
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
uv run python examples/01_hello_tack.py
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
import tack
|
|
24
|
+
|
|
25
|
+
_parser = argparse.ArgumentParser()
|
|
26
|
+
_parser.add_argument('--arch', default='cpu', choices=['cpu', 'metal', 'cuda', 'hip', 'level_zero'])
|
|
27
|
+
_arch = _parser.parse_args().arch
|
|
28
|
+
tack.set_default_device(_arch)
|
|
29
|
+
|
|
30
|
+
# Allocate 1-D arrays (device arrays)
|
|
31
|
+
n = 10
|
|
32
|
+
x = tack.empty((n,))
|
|
33
|
+
y = tack.empty((n,))
|
|
34
|
+
out = tack.empty((n,))
|
|
35
|
+
|
|
36
|
+
# Upload data from numpy
|
|
37
|
+
tack.copyto(x, np.arange(n, dtype=np.float32)) # [0, 1, 2, ..., 9]
|
|
38
|
+
tack.copyto(y, np.ones(n, dtype=np.float32) * 10.0) # [10, 10, ..., 10]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@tack.kernel
|
|
42
|
+
def add(x, y, out):
|
|
43
|
+
# The top-level for-range is parallelized across threads
|
|
44
|
+
for i in range(x.shape[0]):
|
|
45
|
+
out[i] = x[i] + y[i]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# Run the kernel
|
|
49
|
+
add(x, y, out)
|
|
50
|
+
|
|
51
|
+
# Download result to numpy and print
|
|
52
|
+
result = out.numpy()
|
|
53
|
+
print("x =", x.numpy())
|
|
54
|
+
print("y =", y.numpy())
|
|
55
|
+
print("out=", result)
|
|
56
|
+
assert np.allclose(result, np.arange(n) + 10.0)
|
|
57
|
+
print("\nAll correct!")
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
"""02 -- Math builtins available inside kernels.
|
|
5
|
+
|
|
6
|
+
Tack kernels have access to standard math functions without any imports.
|
|
7
|
+
They compile to hardware intrinsics (LLVM on CPU, device functions on GPU).
|
|
8
|
+
|
|
9
|
+
Available: sqrt, sin, cos, tan, asin, acos, atan, atan2,
|
|
10
|
+
exp, exp2, log, log2, log10, floor, ceil,
|
|
11
|
+
abs, min, max, pow
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
uv run python examples/02_math_builtins.py
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
import tack
|
|
22
|
+
|
|
23
|
+
_parser = argparse.ArgumentParser()
|
|
24
|
+
_parser.add_argument('--arch', default='cpu', choices=['cpu', 'metal', 'cuda', 'hip', 'level_zero'])
|
|
25
|
+
_arch = _parser.parse_args().arch
|
|
26
|
+
tack.set_default_device(_arch)
|
|
27
|
+
|
|
28
|
+
n = 256
|
|
29
|
+
x = tack.empty((n,))
|
|
30
|
+
out_sqrt = tack.empty((n,))
|
|
31
|
+
out_sin = tack.empty((n,))
|
|
32
|
+
out_combined = tack.empty((n,))
|
|
33
|
+
|
|
34
|
+
tack.copyto(x, np.linspace(0.1, 10.0, n, dtype=np.float32))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@tack.kernel
|
|
38
|
+
def apply_math(x, out_sqrt, out_sin, out_combined):
|
|
39
|
+
for i in range(x.shape[0]):
|
|
40
|
+
out_sqrt[i] = sqrt(x[i])
|
|
41
|
+
out_sin[i] = sin(x[i])
|
|
42
|
+
# Mix several builtins in one expression
|
|
43
|
+
out_combined[i] = exp(-x[i]) * cos(x[i] * 3.14159) + abs(log(x[i]))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
apply_math(x, out_sqrt, out_sin, out_combined)
|
|
47
|
+
|
|
48
|
+
np_x = x.numpy()
|
|
49
|
+
print("sqrt error:", np.max(np.abs(out_sqrt.numpy() - np.sqrt(np_x))))
|
|
50
|
+
print("sin error:", np.max(np.abs(out_sin.numpy() - np.sin(np_x))))
|
|
51
|
+
|
|
52
|
+
expected = np.exp(-np_x) * np.cos(np_x * 3.14159) + np.abs(np.log(np_x))
|
|
53
|
+
print("combo error:", np.max(np.abs(out_combined.numpy() - expected)))
|
|
54
|
+
print("\nAll within float32 tolerance!")
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
"""03 -- Scalar arguments: pass Python numbers directly to kernels.
|
|
5
|
+
|
|
6
|
+
Kernels can accept plain Python int/float values alongside arrays.
|
|
7
|
+
This is useful for passing constants like time steps, coefficients,
|
|
8
|
+
or array sizes without creating an array.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
uv run python examples/03_scalar_args.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
import tack
|
|
19
|
+
|
|
20
|
+
_parser = argparse.ArgumentParser()
|
|
21
|
+
_parser.add_argument('--arch', default='cpu', choices=['cpu', 'metal', 'cuda', 'hip', 'level_zero'])
|
|
22
|
+
_arch = _parser.parse_args().arch
|
|
23
|
+
tack.set_default_device(_arch)
|
|
24
|
+
|
|
25
|
+
n = 1000
|
|
26
|
+
x = tack.empty((n,))
|
|
27
|
+
y = tack.empty((n,))
|
|
28
|
+
out = tack.empty((n,))
|
|
29
|
+
|
|
30
|
+
tack.copyto(x, np.arange(n, dtype=np.float32))
|
|
31
|
+
tack.copyto(y, np.ones(n, dtype=np.float32) * 3.0)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@tack.kernel
|
|
35
|
+
def saxpy(x, y, out, alpha, n):
|
|
36
|
+
"""out = alpha * x + y (SAXPY: Single-precision A*X Plus Y)"""
|
|
37
|
+
for i in range(n):
|
|
38
|
+
out[i] = alpha * x[i] + y[i]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Pass scalar values directly -- no need to wrap in arrays
|
|
42
|
+
alpha = 2.5
|
|
43
|
+
saxpy(x, y, out, alpha, n)
|
|
44
|
+
|
|
45
|
+
result = out.numpy()
|
|
46
|
+
expected = alpha * np.arange(n, dtype=np.float32) + 3.0
|
|
47
|
+
assert np.allclose(result, expected)
|
|
48
|
+
print(f"SAXPY with alpha={alpha}: first 5 results = {result[:5]}")
|
|
49
|
+
|
|
50
|
+
# Call again with a different alpha -- same compiled kernel is reused
|
|
51
|
+
saxpy(x, y, out, -1.0, n)
|
|
52
|
+
result2 = out.numpy()
|
|
53
|
+
expected2 = -1.0 * np.arange(n, dtype=np.float32) + 3.0
|
|
54
|
+
assert np.allclose(result2, expected2)
|
|
55
|
+
print(f"SAXPY with alpha=-1.0: first 5 results = {result2[:5]}")
|
|
56
|
+
print("\nScalar arguments work correctly!")
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
"""04 -- Control flow: if/else, while loops, break, ternary expressions.
|
|
5
|
+
|
|
6
|
+
Tack kernels support standard Python control flow. The top-level for-range
|
|
7
|
+
is parallelized; everything inside runs per-thread.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
uv run python examples/04_control_flow.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
import tack
|
|
18
|
+
|
|
19
|
+
_parser = argparse.ArgumentParser()
|
|
20
|
+
_parser.add_argument('--arch', default='cpu', choices=['cpu', 'metal', 'cuda', 'hip', 'level_zero'])
|
|
21
|
+
_arch = _parser.parse_args().arch
|
|
22
|
+
tack.set_default_device(_arch)
|
|
23
|
+
|
|
24
|
+
n = 256
|
|
25
|
+
x = tack.empty((n,))
|
|
26
|
+
out = tack.empty((n,))
|
|
27
|
+
|
|
28
|
+
data = np.arange(n, dtype=np.float32) - 128.0 # [-128, ..., 127]
|
|
29
|
+
tack.copyto(x, data)
|
|
30
|
+
|
|
31
|
+
# --- Example 1: if/else (ReLU activation) ---
|
|
32
|
+
|
|
33
|
+
@tack.kernel
|
|
34
|
+
def relu(x, out):
|
|
35
|
+
for i in range(x.shape[0]):
|
|
36
|
+
if x[i] > 0.0:
|
|
37
|
+
out[i] = x[i]
|
|
38
|
+
else:
|
|
39
|
+
out[i] = 0.0
|
|
40
|
+
|
|
41
|
+
relu(x, out)
|
|
42
|
+
assert np.allclose(out.numpy(), np.maximum(data, 0.0))
|
|
43
|
+
print("1. ReLU (if/else): OK")
|
|
44
|
+
|
|
45
|
+
# --- Example 2: while loop with early exit ---
|
|
46
|
+
|
|
47
|
+
@tack.kernel
|
|
48
|
+
def collatz_steps(x, out):
|
|
49
|
+
"""Count Collatz steps until reaching 1."""
|
|
50
|
+
for i in range(x.shape[0]):
|
|
51
|
+
val = abs(x[i]) + 1.0 # ensure positive, > 0
|
|
52
|
+
steps = 0.0
|
|
53
|
+
while val > 1.0:
|
|
54
|
+
if val > 1000.0:
|
|
55
|
+
break # safety limit
|
|
56
|
+
n_int = int(val)
|
|
57
|
+
if n_int % 2 == 0:
|
|
58
|
+
val = val / 2.0
|
|
59
|
+
else:
|
|
60
|
+
val = val * 3.0 + 1.0
|
|
61
|
+
steps = steps + 1.0
|
|
62
|
+
out[i] = steps
|
|
63
|
+
|
|
64
|
+
collatz_steps(x, out)
|
|
65
|
+
print("2. Collatz steps (while + break): OK, first 5 steps =", out.numpy()[:5])
|
|
66
|
+
|
|
67
|
+
# --- Example 3: ternary expression ---
|
|
68
|
+
|
|
69
|
+
@tack.kernel
|
|
70
|
+
def clamp(x, out):
|
|
71
|
+
"""Clamp values to [-50, 50] using ternary expressions."""
|
|
72
|
+
for i in range(x.shape[0]):
|
|
73
|
+
v = x[i]
|
|
74
|
+
v = v if v > -50.0 else -50.0
|
|
75
|
+
v = v if v < 50.0 else 50.0
|
|
76
|
+
out[i] = v
|
|
77
|
+
|
|
78
|
+
clamp(x, out)
|
|
79
|
+
expected = np.clip(data, -50.0, 50.0)
|
|
80
|
+
assert np.allclose(out.numpy(), expected)
|
|
81
|
+
print("3. Clamp (ternary): OK")
|
|
82
|
+
|
|
83
|
+
# --- Example 4: nested loops ---
|
|
84
|
+
|
|
85
|
+
n2 = 16
|
|
86
|
+
mat = tack.empty((n2 * n2,))
|
|
87
|
+
|
|
88
|
+
@tack.kernel
|
|
89
|
+
def fill_checkerboard(mat):
|
|
90
|
+
for i in range(16):
|
|
91
|
+
for j in range(16):
|
|
92
|
+
if (i + j) % 2 == 0:
|
|
93
|
+
mat[i * 16 + j] = 1.0
|
|
94
|
+
else:
|
|
95
|
+
mat[i * 16 + j] = 0.0
|
|
96
|
+
|
|
97
|
+
fill_checkerboard(mat)
|
|
98
|
+
board = mat.numpy().reshape(16, 16)
|
|
99
|
+
print("4. Checkerboard (nested loops): OK")
|
|
100
|
+
print(" Top-left 4x4:")
|
|
101
|
+
for row in board[:4]:
|
|
102
|
+
print(" ", " ".join(f"{v:.0f}" for v in row[:4]))
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
"""05 -- Multi-dimensional parallel iteration with tack.ndindex.
|
|
5
|
+
|
|
6
|
+
Instead of computing linear indices manually, use tack.ndindex(w, h) to
|
|
7
|
+
iterate over a 2D grid in parallel. Each (i, j) pair maps to a separate
|
|
8
|
+
GPU thread.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
uv run python examples/05_ndindex.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
import tack
|
|
19
|
+
|
|
20
|
+
_parser = argparse.ArgumentParser()
|
|
21
|
+
_parser.add_argument('--arch', default='cpu', choices=['cpu', 'metal', 'cuda', 'hip', 'level_zero'])
|
|
22
|
+
_arch = _parser.parse_args().arch
|
|
23
|
+
tack.set_default_device(_arch)
|
|
24
|
+
|
|
25
|
+
width, height = 64, 64
|
|
26
|
+
pixels = tack.empty((width, height))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@tack.kernel
|
|
30
|
+
def distance_array(pixels):
|
|
31
|
+
"""Compute distance from center for each pixel."""
|
|
32
|
+
for i, j in tack.ndindex(64, 64):
|
|
33
|
+
dx = float(i) - 32.0
|
|
34
|
+
dy = float(j) - 32.0
|
|
35
|
+
pixels[i, j] = sqrt(dx * dx + dy * dy)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
distance_array(pixels)
|
|
39
|
+
|
|
40
|
+
result = pixels.numpy().reshape(64, 64)
|
|
41
|
+
# Check center is ~0, corners are ~45
|
|
42
|
+
assert result[32, 32] == 0.0
|
|
43
|
+
corner_dist = result[0, 0]
|
|
44
|
+
assert abs(corner_dist - np.sqrt(32**2 + 32**2)) < 0.01
|
|
45
|
+
print(f"Center distance: {result[32, 32]:.2f} (expected 0)")
|
|
46
|
+
print(f"Corner distance: {corner_dist:.2f} (expected {np.sqrt(32**2+32**2):.2f})")
|
|
47
|
+
|
|
48
|
+
# --- Example 2: 2D Gaussian blur (3x3 kernel) ---
|
|
49
|
+
|
|
50
|
+
src = tack.empty((64, 64))
|
|
51
|
+
dst = tack.empty((64, 64))
|
|
52
|
+
|
|
53
|
+
# Create a simple image: bright spot at center
|
|
54
|
+
img = np.zeros((64, 64), dtype=np.float32)
|
|
55
|
+
img[32, 32] = 100.0
|
|
56
|
+
tack.copyto(src, img)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@tack.kernel
|
|
60
|
+
def blur_3x3(src, dst):
|
|
61
|
+
"""Simple 3x3 box blur, skipping borders."""
|
|
62
|
+
for i, j in tack.ndindex(64, 64):
|
|
63
|
+
if i > 0:
|
|
64
|
+
if i < 63:
|
|
65
|
+
if j > 0:
|
|
66
|
+
if j < 63:
|
|
67
|
+
s = 0.0
|
|
68
|
+
for di in range(-1, 2):
|
|
69
|
+
for dj in range(-1, 2):
|
|
70
|
+
s = s + src[i + di, j + dj]
|
|
71
|
+
dst[i, j] = s / 9.0
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
blur_3x3(src, dst)
|
|
75
|
+
blurred = dst.numpy().reshape(64, 64)
|
|
76
|
+
print(f"\nBlur: center pixel {blurred[32,32]:.2f} (was 100.00)")
|
|
77
|
+
print(f"Blur: neighbor {blurred[32,33]:.2f} (was 0.00)")
|
|
78
|
+
print("2D ndindex + stencil: OK")
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
|
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
3
|
+
|
|
4
|
+
"""06 -- Device functions with @tack.func.
|
|
5
|
+
|
|
6
|
+
Use @tack.func to define helper functions that are inlined into kernels
|
|
7
|
+
at compile time. This keeps kernels clean and lets you reuse logic.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
uv run python examples/06_device_functions.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
import tack
|
|
18
|
+
|
|
19
|
+
_parser = argparse.ArgumentParser()
|
|
20
|
+
_parser.add_argument('--arch', default='cpu', choices=['cpu', 'metal', 'cuda', 'hip', 'level_zero'])
|
|
21
|
+
_arch = _parser.parse_args().arch
|
|
22
|
+
tack.set_default_device(_arch)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# --- Device function: inlined wherever called ---
|
|
26
|
+
|
|
27
|
+
@tack.func
|
|
28
|
+
def lerp(a, b, t):
|
|
29
|
+
"""Linear interpolation: a*(1-t) + b*t"""
|
|
30
|
+
return a + t * (b - a)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@tack.func
|
|
34
|
+
def smoothstep(edge0, edge1, x):
|
|
35
|
+
"""Hermite smoothstep interpolation."""
|
|
36
|
+
t = (x - edge0) / (edge1 - edge0)
|
|
37
|
+
t = max(0.0, min(1.0, t))
|
|
38
|
+
return t * t * (3.0 - 2.0 * t)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@tack.func
|
|
42
|
+
def remap(value, in_lo, in_hi, out_lo, out_hi):
|
|
43
|
+
"""Remap a value from one range to another."""
|
|
44
|
+
t = (value - in_lo) / (in_hi - in_lo)
|
|
45
|
+
return lerp(out_lo, out_hi, t) # device functions can call each other
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# --- Kernel using device functions ---
|
|
49
|
+
|
|
50
|
+
n = 100
|
|
51
|
+
x = tack.empty((n,))
|
|
52
|
+
out_lerp = tack.empty((n,))
|
|
53
|
+
out_smooth = tack.empty((n,))
|
|
54
|
+
out_remap = tack.empty((n,))
|
|
55
|
+
|
|
56
|
+
tack.copyto(x, np.linspace(0.0, 1.0, n, dtype=np.float32))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@tack.kernel
|
|
60
|
+
def apply_all(x, out_lerp, out_smooth, out_remap):
|
|
61
|
+
for i in range(x.shape[0]):
|
|
62
|
+
t = x[i]
|
|
63
|
+
out_lerp[i] = lerp(0.0, 100.0, t)
|
|
64
|
+
out_smooth[i] = smoothstep(0.2, 0.8, t)
|
|
65
|
+
out_remap[i] = remap(t, 0.0, 1.0, -10.0, 10.0)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
apply_all(x, out_lerp, out_smooth, out_remap)
|
|
69
|
+
|
|
70
|
+
print("lerp(0,100,t): ", out_lerp.numpy()[[0, 25, 50, 75, 99]])
|
|
71
|
+
print("smoothstep: ", out_smooth.numpy()[[0, 25, 50, 75, 99]])
|
|
72
|
+
print("remap(0,1,-10,10):", out_remap.numpy()[[0, 25, 50, 75, 99]])
|
|
73
|
+
|
|
74
|
+
# Verify lerp
|
|
75
|
+
assert np.allclose(out_lerp.numpy(), np.linspace(0, 100, n))
|
|
76
|
+
# Verify remap
|
|
77
|
+
assert np.allclose(out_remap.numpy(), np.linspace(-10, 10, n))
|
|
78
|
+
print("\nDevice functions: OK")
|