Skip to main content

A Python library for performing operations on tensors with infinite dimensions.

Project description

Infinite Tensors

A Python library for performing operations on theoretically infinite tensors using a sliding window approach. This library enables processing of large tensors without loading the entire tensor into memory.

Installation

Install using pip:

pip install infinite-tensor

What is an Infinite Tensor?

An Infinite Tensor represents an immutable tensor with one or more unbounded dimensions, defined by a deterministic function f. Instead of loading all data into memory at once, it:

  • Loads only the parts you need, when you need them
  • Processes data in manageable windows
  • Caches results so repeated reads are instant

Internally, when you index a region, the system identifies which output windows intersect that region, invokes f on each, and sums the outputs together. Results are cached, and no data outside the requested region is generated.

Key Concepts

  1. Windows: Define how your processing function sees the data

    • Fixed size (e.g., 64x64 pixels)
    • Outputs in overlapping regions are added together
    • Defined by size, stride, and offset
  2. Infinite Tensors: Immutable tensors with infinite dimensions

    • Some dimensions can be None (infinite), others must be finite
    • Defined by a deterministic function f operating on the "output window"
    • Can depend on other infinite tensors

Getting Started

1. Creating an Infinite Tensor

Always create tensors through a TileStore:

import uuid
import torch
from infinite_tensor import TensorWindow, MemoryTileStore

# Create a tile store (in-memory)
tile_store = MemoryTileStore()

# Define how each window is generated; must match the window's shape
def your_processing_function(ctx):
    # ctx is the window index (e.g., (wy, wx) for 2D). It is NOT pixel coordinates.
    return torch.ones(512, 512)

# Define the output window seen by your function
window = TensorWindow((512, 512))

# Create an infinite tensor (2D infinite)
tensor = tile_store.get_or_create(
    "my_infinite_tensor",
    shape=(None, None),         # None means infinite dimension
    f=your_processing_function, # A function that takes the index of the current output window as input: e.g (0, 0)
    output_window=window,
    tile_size=512,              # internal tile size (optional)
)

2. Using the Tensor

Just slice it like a normal tensor (computed on-demand)

result = tensor[0:1024, 0:1024]

Advanced Features

1. Caching Methods

InfiniteTensor supports two caching strategies via cache_method:

  • cache_method='indirect' (default): Window outputs are accumulated into tiles. Best for persistent storage (e.g., HDF5TileStore) since it uses the least disk space. Use tile_size to indicate the size of the tiles.

  • cache_method='direct': Window outputs are cached directly with LRU eviction. Best when you want to limit memory usage and don't need persistent storage. Use cache_limit to set the max cache size in bytes (default: 10MB), or None for unlimited. tile_size is ignored with this method.

2. Dependency Chaining

Create processing pipelines by making one infinite tensor depend on another.

In this case, f is called like f(ctx, *args_sliced), where ctx is the output window index, and args_sliced are the upstream tensors (args) sliced by args_windows.

import torch
from infinite_tensor import TensorWindow, MemoryTileStore

tile_store = MemoryTileStore()

def zeros_tensor_func(ctx):
    return torch.zeros(10, 512, 512)  # (C, H, W)

base_window = TensorWindow((10, 512, 512))
base = tile_store.get_or_create("my_tensor", (10, None, None), zeros_tensor_func, base_window)

# Define an offset window for the dependent tensor
offset_window = TensorWindow((10, 512, 512), offset=(0, -256, -256))

# The function receives the upstream window directly (already sliced)
def inc_func(ctx, prev):
    return prev + 1

dep = tile_store.get_or_create(
    "my_second_tensor",
    (10, None, None),
    inc_func,
    offset_window,
    args=(base,),
    args_windows=(offset_window,),
)

out = dep[:, 0:512, 0:512]  # ones

Note: Manually slicing dependencies inside f is not recommended, as it prevents the use of batching, and future versions may introduce automatic memory management utilizing this future.

3. Batching

Optionally, f can take in a list of tensors, instead of one at a time. The max size of the list is given by batch_size. Here is the same example as above but with batching:

import torch
from infinite_tensor import TensorWindow, MemoryTileStore

tile_store = MemoryTileStore()

def zeros_tensor_func(ctx):
    return torch.zeros(10, 512, 512)  # (C, H, W)

base_window = TensorWindow((10, 512, 512))
base = tile_store.get_or_create("my_tensor", (10, None, None), zeros_tensor_func, base_window)

# Define an offset window for the dependent tensor
offset_window = TensorWindow((10, 512, 512), offset=(0, -256, -256))

# The function receives the upstream window directly (already sliced)
# now prev is a list of up to 4 tensors
def inc_func(ctx, prev):
    # return a list of the same size
    prev_stack = torch.stack(prev)
    return [p for p in (prev_stack + 1)]

dep = tile_store.get_or_create(
    "my_second_tensor",
    (10, None, None),
    inc_func,
    offset_window,
    args=(base,),
    args_windows=(offset_window,),
    batch_size=4
)

out = dep[:, 0:512, 0:512]  # ones

Important Notes

  1. Deterministic f: Your function must be deterministic—results are cached assuming f is pure.
  2. Create via TileStore: Construct tensors with tile_store.get_or_create(...). Direct construction of InfiniteTensor is not supported.
  3. Avoid manual slicing: Do not manually slice dependencies. Use args/args_windows so the framework manages slicing and dependencies.
  4. CPU Only: Outputs and inputs to f are always on the CPU. Returning tensors on other devices will raise errors.
  5. Window Size: Your function must return exactly the size specified in TensorWindow.
  6. Finite Dimensions: Non-infinite dimensions must fit in memory.

Example

Check out examples/blur.py for a complete example showing how to:

  • Process images larger than memory
  • Handle boundaries correctly
  • Chain multiple processing steps

License

MIT License - See LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

infinite_tensor-0.2.3.tar.gz (33.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

infinite_tensor-0.2.3-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file infinite_tensor-0.2.3.tar.gz.

File metadata

  • Download URL: infinite_tensor-0.2.3.tar.gz
  • Upload date:
  • Size: 33.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for infinite_tensor-0.2.3.tar.gz
Algorithm Hash digest
SHA256 ce2187039e34407f63464c00efacb69f251a6f0c463382c4ec7cf0c31b6fe262
MD5 e63ad9a69016482881189e809facd693
BLAKE2b-256 255aaba00b806317b1c5daae246795ddb1c8f430379349c65ef21d2b0a89f9d1

See more details on using hashes here.

File details

Details for the file infinite_tensor-0.2.3-py3-none-any.whl.

File metadata

File hashes

Hashes for infinite_tensor-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 05834cd3c3925a32badc69f5d07f2d0540aae09062ea0ad7b495e3473d856097
MD5 2bdc7af2bef2fb013c2538415f76744c
BLAKE2b-256 beed7b6d123bb1cfd7812dd119b8d5c4c4df9e72738e8e0f09337cd76ecd5a9f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page