Getting Started¶
Installation¶
Use Python 3.11 or newer. Tack compiles kernels at runtime; installing the Python packages needs no Tack build step. Start with the CPU backend so the first example needs no GPU runtime.
Follow this guide from source¶
The guide and its tutorial scripts describe the current checkout, including unreleased additions. To use the same API and run the commands shown throughout the guide, install the checkout with uv:
git clone https://github.com/berkgeveci/tack.git
cd tack
uv sync --extra cpu
Run Python with uv run python from this directory. Both Tack packages are
installed: tack-core for compute and tack-vis for datasets and scientific
visualization.
Install into another environment¶
Tack is not on PyPI yet. For a separate application, create an environment
and install the packages from the clone, tack-core first:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e '/path/to/tack/packages/tack-core[cpu]'
# Optional: datasets and visualization
python -m pip install -e /path/to/tack/packages/tack-vis
On Windows, activate with .venv\Scripts\Activate.ps1 in PowerShell. Run scripts
with python in the activated environment. Download tutorial scripts from their
pages instead of using checkout-relative paths such as docs/examples/heat.py.
An installed release may lack APIs added in the checkout. If an example uses
an unavailable API, check the release notes or use the source installation above.
A bare tack-core install does not include the CPU JIT dependency; the [cpu]
extra does. The visualization package also needs a working backend.
Your First Kernel¶
Save the following complete program as first_kernel.py. Tack needs the
decorated function's source, so a .py file is the starting point for this guide.
import numpy as np
import tack
tack.set_default_device("cpu")
# Create arrays from numpy arrays
n = 1024
x = tack.array(np.arange(n, dtype=np.float32))
y = tack.array(np.ones(n, dtype=np.float32) * 2.0)
out = tack.empty((n,))
# Define a kernel
@tack.kernel
def vector_add(x, y, out):
for i in range(x.shape[0]):
out[i] = x[i] + y[i]
# Run it
vector_add(x, y, out)
# Read results back to numpy
result = out.numpy()
np.testing.assert_array_equal(result, np.arange(n, dtype=np.float32) + 2.0)
print(result[:5]) # [2. 3. 4. 5. 6.]
Run it from the checkout:
uv run python first_kernel.py
Or use python first_kernel.py in your installed environment. You should see:
[2. 3. 4. 5. 6.]
A kernel is a Python function decorated with @tack.kernel. The outermost
for i in range(...) becomes a parallel loop — each iteration runs as a
separate thread on the GPU (or is split across CPU cores).
Choosing a Backend¶
After the CPU example works, install your backend's extra and replace the
single tack.set_default_device line. For a checkout, keep --extra cpu if you want both:
| Hardware | Checkout installation | Default device |
|---|---|---|
| CPU | uv sync --extra cpu |
tack.set_default_device("cpu") |
| Apple silicon GPU | uv sync --extra cpu --extra metal |
tack.set_default_device("metal") |
| NVIDIA GPU | uv sync --extra cpu --extra cuda |
tack.set_default_device("cuda") |
| AMD GPU | uv sync --extra cpu --extra hip |
tack.set_default_device("hip") |
| Intel GPU | uv sync --extra cpu --extra level_zero |
tack.set_default_device("level_zero") |
For released packages, use the matching extra, such as tack-core[cuda].
GPU extras also require compatible system runtimes; see Backends.
The supplied tutorial scripts accept --arch on the command line; the small
first_kernel.py above selects its backend in code:
uv run python packages/tack-core/examples/01_hello_tack.py --arch metal
This kernel uses the portable numerical subset and runs on all five backends.
Backend capabilities still matter: Metal has no f64, and CPU has no shared
workgroup memory. Initialize before allocating arrays; a later backend switch
does not migrate them.
How It Works¶
The execution-model chapter develops these ideas through examples. You can continue there now; the compilation outline below is optional on a first reading.
When you call a kernel for the first time, Tack:
- Reads the Python source of the decorated function
- Transforms the AST into Tack's internal IR
- Resolves shapes and types, then propagates safe copies
- Generates backend-specific code (LLVM IR, MSL, CUDA C, etc.)
- Compiles and dispatches
LLVM and vendor compilers optimize the generated code. Subsequent calls with the same specialization reuse the compiled kernel; dtypes, vector widths, baked-in shapes, and template structure can require another variant. Compiled kernels are also kept on disk, so the next process that calls the same kernel loads it instead of compiling it; see The Kernel Cache.
A useful next step¶
Read From Python to a Tack program to understand the host/kernel boundary, then work through Heat diffusion. The tutorial gallery offers six complete programs with figures, downloadable source, and checks of their results.
The numerical tutorials need NumPy and the selected Tack backend. To save their optional plots, also install VTK:
pip install vtk
# From a uv checkout, without changing project dependencies:
uv run --with vtk python docs/examples/heat.py --output heat.png
# Or keep VTK in the checkout's environment (uv sync would otherwise remove it):
uv sync --extra cpu --extra interop