InstantTensor
InstantTensor is an ultra-fast, distributed Safetensors loader designed to maximize I/O throughput when moving model weights from Safetensors files to GPU memory.
Model loading benchmark on inference engines
| Model | GPU | Backend | Load Time (s) | Throughput (GB/s) | Speedup |
|---|---|---|---|---|---|
| Qwen3-30B-A3B | 1*H200 | Safetensors | 57.4 | 1.1 | 1x |
| Qwen3-30B-A3B | 1*H200 | InstantTensor | 1.77 | 35 | 32.4x |
| DeepSeek-R1 | 8*H200 | Safetensors | 160 | 4.3 | 1x |
| DeepSeek-R1 | 8*H200 | InstantTensor | 15.3 | 45 | 10.5x |
See Benchmark for full benchmarks.
Quickstart
from instanttensor import safe_open
tensors = {}
with safe_open("model.safetensors", framework="pt", device=0) as f:
for name, tensor in f.tensors():
tensors[name] = tensor
Yielded tensors own their memory by default (copy=True). For zero-copy
streaming into preallocated storage, see Zero-copy mode.
See Usage for multi-file and distributed usage.
Used by
Why InstantTensor?
- Fast: Pipeline I/O, GPU transfers, and prefetching.
- Distributed: Coordinate reads across GPUs with NCCL.
- Selective: Load only the tensors you need.
- Flexible: Support Direct I/O, Buffered I/O, MMAP, and GPUDirect Storage.
- Memory-aware: Reuse configurable staging buffers, with optional zero-copy views.
When to Use InstantTensor
- Loading large checkpoints from fast storage.
- Cold starts or model switching with limited host-memory cache.
- Multi-GPU loading from shared checkpoints.
- Loading only part of a checkpoint, such as MTP weights.
- Repeated loading from the page cache or tmpfs.
Performance depends on your hardware and workload; benchmark before choosing.
Installation
Requirements
- GPU platforms: CUDA, ROCm
- Framework: PyTorch
URING/URING_BUFFERED: Linux kernel 5.6 or newer; 5.15 or newer is recommended
Method 1: Install from pip
pip install instanttensor
Method 2: Build from source
git clone https://github.com/scitix/InstantTensor.git
cd InstantTensor
./checkout_submodules.sh
pip install .
# For a debug build, set "DEBUG=1" before "pip"
Usage
Distributed loading
InstantTensor can use a torch.distributed NCCL process group to coordinate loading and achieve higher throughput compared to running safe_open independently on each GPU.
Passing all files in a single safe_open call lets the backend plan reads across files and typically provides higher throughput than loading each file separately. This applies to both single-GPU and distributed loading.
import torch
import torch.distributed as dist
from instanttensor import safe_open
dist.init_process_group(backend="nccl")
process_group = dist.GroupMember.WORLD
files = ["model-00001-of-00002.safetensors", "model-00002-of-00002.safetensors"]
tensors = {}
with safe_open(files, framework="pt", device=torch.cuda.current_device(), process_group=process_group) as f:
for name, tensor in f.tensors():
tensors[name] = tensor
NOTE: You can also load weights using a subgroup created via
dist.new_group, which allows multiple subgroups to load weights independently. For example, if you have TP=8 and PP=2 (i.e., two TP groups), you can create two subgroups and load weights independently on each TP group. In cross-node (multi-machine) scenarios, loading using per-node subgroups can sometimes be faster than loading on the world group. However, for most cases, the world group is a good default choice.
Selective loading
Use tensor_filter to skip tensor payloads before I/O. Buffer sizing,
keys(), and total_tensor_size include only selected tensors. Reads may
include neighboring bytes required for page alignment.
with safe_open(files, framework="pt", device=0,
tensor_filter=["model.embed_tokens.weight", "model.layers.0.*"]) as f:
for name, tensor in f.tensors():
tensors[name] = tensor
Filtering requires process_group=None: each GPU loads its own selection
independently. Unfiltered distributed loading is unchanged.
Use tensor_name_match_mode to choose how all entries in the list are interpreted:
| Mode | Example | Matching |
|---|---|---|
"glob" (default) |
"model.layers.*.weight" |
Shell-style wildcards (*, ?, [abc]); dots are literal. |
"exact" |
"model.layers.0.weight" |
Literal full names, including any wildcard or regex characters. |
"regex" |
r"model\.layers\.\d+\.weight" |
Full-match regular expressions (re.fullmatch). |
Matching is case-sensitive by default and selects a tensor if any pattern matches its
whole name; the mode is never inferred from checkpoint contents. In glob mode,
* can span dots, and names containing wildcard characters need escaping or
tensor_name_match_mode="exact". None selects all tensors and [] selects none.
With copy=False, consume each tensor inline
because alignment padding can cause buffer reuse even when tensor bytes fit.
Buffered I/O
For regular disk files, InstantTensor defaults to Direct I/O to prioritize cold load performance. This is usually the right choice when a model is loaded once for a long-running workload.
If the same model is loaded repeatedly within a short period, Buffered I/O can
be faster because later reads may benefit from the page cache. Enable it with
the backend=BackendPolicy.BUFFERED argument to safe_open, or, when
backend=None, by setting the INSTANTTENSOR_BACKEND=BUFFERED environment
variable.
Zero-copy mode
Pass copy=False to skip the per-tensor clone and yield views into the
internal ring buffer:
with safe_open(files, framework="pt", device=0, copy=False) as f:
for name, tensor in f.tensors():
model_param[name].copy_(tensor)
Two rules:
- Consume each tensor before the next is yielded —
list(f.tensors())and similar patterns silently corrupt data whenbuffer_size < total_tensor_size. - Do not keep references past the
withblock — the buffer is freed on exit.
A UserWarning fires when copy=False and buffer_size < total_tensor_size.
Both attributes are public on the safe_open object.
See tests/test.py for a full benchmark harness (TP/PP grouping, checksums, etc.).
Backend selection
InstantTensor selects an I/O backend automatically by default. You can provide
one or more backend candidates with the backend argument to safe_open, or
with the INSTANTTENSOR_BACKEND environment variable when backend=None.
InstantTensor tries the candidates in order and uses the first backend that is
supported by the file system and available on the current system.
Supported backend values are Backend.AIO, Backend.AIO_BUFFERED,
Backend.URING, Backend.URING_BUFFERED, Backend.CUFILE, and
Backend.MMAP. The backend argument accepts a single Backend or a list of
Backend/BackendPolicy values:
from instanttensor import Backend, BackendPolicy, safe_open
safe_open("model.safetensors", framework="pt", device=0, backend=Backend.URING)
safe_open("model.safetensors", framework="pt", device=0, backend=[Backend.URING, Backend.AIO])
safe_open("model.safetensors", framework="pt", device=0, backend=BackendPolicy.BUFFERED)
BackendPolicy.BUFFERED expands to [Backend.URING_BUFFERED, Backend.MMAP]. This is a
good choice when you want Buffered I/O. AIO_BUFFERED remains available when selected
explicitly.
INSTANTTENSOR_BACKEND accepts comma-separated backend or policy names:
INSTANTTENSOR_BACKEND=URING,AIO
INSTANTTENSOR_BACKEND=BUFFERED
Backends are used in different file-system and I/O scenarios:
- In-memory file systems (available backends:
MMAP,URING_BUFFERED,AIO_BUFFERED): when model files are stored on tmpfs or ramfs,MMAPprovides the best compatibility and performance for this case. The other backends are usually slower for in-memory files. - Regular file systems: InstantTensor can use either Direct I/O or Buffered
I/O.
- Direct I/O (available backends:
AIO,URING,CUFILE) is best when a model is loaded once for a long-running workload. It avoids page-cache cold-start effects and reduces page-cache pollution. When choosing manually,URINGmay be faster on newer platforms.AIOhas the broadest platform compatibility.CUFILErequires GPUDirect Storage support, and its higher throughput can be offset by cuFile initialization overhead. - Buffered I/O (available backends:
AIO_BUFFERED,URING_BUFFERED,MMAP) is best when the same model is loaded repeatedly within a short period. Later reads can benefit from the page cache, though the first read is usually slower than Direct I/O.URING_BUFFEREDis preferred on platforms with io_uring support;AIO_BUFFEREDprovides a more compatible option, whileMMAPis available but usually not preferred.
- Direct I/O (available backends:
If no backend is specified, InstantTensor tries [URING, AIO] for regular disk
files. For tmpfs/ramfs files, it uses MMAP. If none of the requested
candidates can be used, InstantTensor raises an error listing why each candidate
was rejected.
Environment variables
Set these variables before the first safe_open call. An explicit safe_open
argument takes precedence over its corresponding environment variable.
| Variable | Description | Default |
|---|---|---|
INSTANTTENSOR_BACKEND |
Comma-separated backend or policy candidates, for example URING,AIO or BUFFERED. |
Automatically select by filesystem type. |
INSTANTTENSOR_BUFFER_SIZE |
Requested logical GPU tensor ring-buffer size in bytes. It constrains io_depth but may be enlarged to fit the largest tensor. |
Automatically determined from tensor sizes and I/O settings. |
INSTANTTENSOR_CHUNK_SIZE |
File I/O chunk size in bytes. | Automatically determined for the selected backend. |
INSTANTTENSOR_CONCURRENCY |
Number of worker threads for MMAP and CUFILE; other backends ignore it. |
Automatically determined for the selected backend. |
INSTANTTENSOR_IO_DEPTH |
Maximum number of rank-local I/O operations in flight. Higher values can increase throughput and staging-memory usage; the maximum is 1024. | Automatically determined for the selected backend. |
INSTANTTENSOR_MAX_FREE_MEM_USAGE |
Maximum fraction of currently free GPU memory available to the logical device buffer. | 0.5 |
INSTANTTENSOR_CACHE_BUFFER |
Set to 1 to cache pinned host staging buffers across loader opens. Cached memory remains pinned until process cleanup. |
0 |
INSTANTTENSOR_DEBUG |
Set to 1 to print backend selection, buffer sizes, timing, and throughput diagnostics. |
0 |
The I/O capacity required by a configuration is
round_up(chunk_size, page_size) * io_depth * world_size. When buffer_size
is omitted, InstantTensor chooses the larger of this value and the
tensor-layout recommendation. When buffer_size and io_depth are both set,
they must be compatible. When only buffer_size is set, InstantTensor reduces
the default io_depth as needed. The internal device allocation includes a
small additional alignment guard beyond the logical buffer_size. If the
final logical buffer exceeds the resulting device-memory budget, opening fails
before the native allocation is attempted.
For example:
INSTANTTENSOR_BACKEND=BUFFERED \
INSTANTTENSOR_IO_DEPTH=32 \
INSTANTTENSOR_DEBUG=1 python load_model.py
API reference
Thanks
Thanks to the AI Systems and Optimization team at ScitiX AI and the Wenfei Wu Lab at Peking University.
Metadata
Release files for instanttensor 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| instanttensor-0.2.2.tar.gz | 613.1 kB | Details |
Built distributions (wheels)
Total release size: 65.2 MB
Release files / instanttensor-0.2.2.tar.gz
| Download URL | instanttensor-0.2.2.tar.gz |
|---|---|
| Size | 613.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aca07c1afe4fde23dcbfb53044e2bef50dad4c0af054317acc669a1c8dc2b325
|
|
BLAKE2b-256 checksum How to use checksums |
caa195d0d4cee908ab0bd8e56b44cdb19e678081c54de52d280b0b3c9f7e4c43
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | instanttensor-0.2.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 6.5 MB |
| Tags | CPython 3.14 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
0ccf832e544dcd13aac8da280ce70ad1b2bfede4fc00a7e7e3e6f963e3dd7eb4
|
|
BLAKE2b-256 checksum How to use checksums |
652e7bf9604ed24f24a254c20754c0ded92c416242ab1f24628d614a41f548f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
| Download URL | instanttensor-0.2.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | CPython 3.14 Linux glibc 2.26+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
4b5ea4b516a372ef7f54e33324be10c289288f7ef57a0667b8a321293091c249
|
|
BLAKE2b-256 checksum How to use checksums |
56b7a659fc9f2e2510a127216beb1eb909fec6bacb6c404f903e3e307daf5957
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | instanttensor-0.2.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 6.5 MB |
| Tags | CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
0474ae1f12bccbd01fabaeffab483870d9be644dc5c52d8b746ee1806dbc02fe
|
|
BLAKE2b-256 checksum How to use checksums |
54450ade43f9fa2ae52bcdb7c1dad7ae190919f4e1a97a2f88dc6131ac00fb37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
| Download URL | instanttensor-0.2.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | CPython 3.13 Linux glibc 2.26+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
fd1757e57d9561a6c28dfb18568890fd50d1f3e331d7ec247034c011f3086be9
|
|
BLAKE2b-256 checksum How to use checksums |
cdd7b7a4d6f57a7b5d76377ab0660f152e4cabb3ccc4a55c36e14f7fd6ecbda1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | instanttensor-0.2.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 6.5 MB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
382954f2329fc085ff298ce0205a06ce0fc8c67a704fc032613931a5ae9018d5
|
|
BLAKE2b-256 checksum How to use checksums |
59120a4b55402ec7f45f223d4cab19c8d6d39f5242d386f4f421e30c34dd8900
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
| Download URL | instanttensor-0.2.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | CPython 3.12 Linux glibc 2.26+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
94dabc13981fe89982a807572593c4f697a3a3bae02fa13cb469960885901247
|
|
BLAKE2b-256 checksum How to use checksums |
ff08a28ad4c33e42f45d5617f8feb24137fcc1b7af7a7f0068c3fcf3448a0806
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | instanttensor-0.2.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 6.5 MB |
| Tags | CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
78ba35382f42e81d18aa9ab59485ff1d1764c846de68bc5de8b894b37ee14996
|
|
BLAKE2b-256 checksum How to use checksums |
a15db8dcff8c81bffe875344b033704fda7a0bc30bf65ff808fff0783f6b3adf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
| Download URL | instanttensor-0.2.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | CPython 3.11 Linux glibc 2.26+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
d43097e15922fd90e45a19308efc2ec63290e51f308f8501eaae705d7249df87
|
|
BLAKE2b-256 checksum How to use checksums |
b85100cd5124d244c9dc988e294bdb4bb85d0355829d6d818a9b459b585ec452
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | instanttensor-0.2.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
1ba19b3c7a9099a6e7ffe644e8bc808244ceb0b3dcefedda48243d90b89cc328
|
|
BLAKE2b-256 checksum How to use checksums |
2378e272f01c0b10549180d58c73a26ac57456854ae0c98d652c81f34ac46938
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / instanttensor-0.2.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
| Download URL | instanttensor-0.2.2-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | CPython 3.10 Linux glibc 2.26+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
559bbce844f6ce043ade31ac73eb67026da8f7c648a37cbbc86d3baf8aec408a
|
|
BLAKE2b-256 checksum How to use checksums |
ebcd06bd5595b5f58738e1f32d9c96e657955a44ce510d00b09c0d1bd156d2a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|