Skip to main content

Optimized PyTree Utilities.

Project description

OpTree

Python 3.7+ PyPI GitHub Workflow Status GitHub Workflow Status Codecov Documentation Status Downloads GitHub Repo Stars

Optimized PyTree Utilities.


Table of Contents


Installation

Install from PyPI (PyPI / Status):

pip3 install --upgrade optree

Install from conda-forge (conda-forge):

conda install -c conda-forge optree

Install the latest version from GitHub:

pip3 install git+https://github.com/metaopt/optree.git#egg=optree

Or, clone this repo and install manually:

git clone --depth=1 https://github.com/metaopt/optree.git
cd optree
pip3 install .

Compiling from the source requires Python 3.7+, a compiler (gcc / clang / icc / cl.exe) that supports C++20 and a cmake installation.


PyTrees

A PyTree is a recursive structure that can be an arbitrarily nested Python container (e.g., tuple, list, dict, OrderedDict, NamedTuple, etc.) or an opaque Python object. The key concepts of tree operations are tree flattening and its inverse (tree unflattening). Additional tree operations can be performed based on these two basic functions (e.g., tree_map = tree_unflatten ∘ map ∘ tree_flatten).

Tree flattening is traversing the entire tree in a left-to-right depth-first manner and returning the leaves of the tree in a deterministic order.

>>> tree = {'b': (2, [3, 4]), 'a': 1, 'c': 5, 'd': 6}
>>> optree.tree_flatten(tree)
([1, 2, 3, 4, 5, 6], PyTreeSpec({'a': *, 'b': (*, [*, *]), 'c': *, 'd': *}))
>>> optree.tree_flatten(1)
([1], PyTreeSpec(*))
>>> optree.tree_flatten(None)
([], PyTreeSpec(None))

This usually implies that the equal pytrees return equal lists of leaves and the same tree structure. See also section Key Ordering for Dictionaries.

>>> {'a': [1, 2], 'b': [3]} == {'b': [3], 'a': [1, 2]}
True
>>> optree.tree_leaves({'a': [1, 2], 'b': [3]}) == optree.tree_leaves({'b': [3], 'a': [1, 2]})
True
>>> optree.tree_structure({'a': [1, 2], 'b': [3]}) == optree.tree_structure({'b': [3], 'a': [1, 2]})
True

Tree Nodes and Leaves

A tree is a collection of non-leaf nodes and leaf nodes, where the leaf nodes have no children to flatten. optree.tree_flatten(...) will flatten the tree and return a list of leaf nodes while the non-leaf nodes will store in the tree specification.

Built-in PyTree Node Types

OpTree out-of-box supports the following Python container types in the registry:

which are considered non-leaf nodes in the tree. Python objects that the type is not registered will be treated as leaf nodes. The registration lookup uses the is operator to determine whether the type is matched. So subclasses will need to explicitly register in the registry, otherwise, an object of that type will be considered a leaf. The NoneType is a special case discussed in section None is non-leaf Node vs. None is Leaf.

Registering a Container-like Custom Type as Non-leaf Nodes

A container-like Python type can be registered in the type registry with a pair of functions that specify:

  • flatten_func(container) -> (children, metadata, entries): convert an instance of the container type to a (children, metadata, entries) triple, where children is an iterable of subtrees and entries is an iterable of path entries of the container (e.g., indices or keys).
  • unflatten_func(metadata, children) -> container: convert such a pair back to an instance of the container type.

The metadata is some necessary data apart from the children to reconstruct the container, e.g., the keys of the dictionary (the children are values).

The entries can be omitted (only returns a pair) or is optional to implement (returns None). If so, use range(len(children)) (i.e., flat indices) as path entries of the current node. The function signature can be flatten_func(container) -> (children, metadata) or flatten_func(container) -> (children, metadata, None).

The following examples show how to register custom types and utilize them for tree_flatten and tree_map. Please refer to section Notes about the PyTree Type Registry for more information.

# Registry a Python type with lambda functions
optree.register_pytree_node(
    set,
    # (set) -> (children, metadata, None)
    lambda s: (sorted(s), None, None),
    # (metadata, children) -> (set)
    lambda _, children: set(children),
    namespace='set',
)

# Register a Python type into a namespace
import torch

optree.register_pytree_node(
    torch.Tensor,
    # (tensor) -> (children, metadata)
    flatten_func=lambda tensor: (
        (tensor.cpu().detach().numpy(),),
        {'dtype': tensor.dtype, 'device': tensor.device, 'requires_grad': tensor.requires_grad},
    ),
    # (metadata, children) -> tensor
    unflatten_func=lambda metadata, children: torch.tensor(children[0], **metadata),
    namespace='torch2numpy',
)
>>> tree = {'weight': torch.ones(size=(1, 2)).cuda(), 'bias': torch.zeros(size=(2,))}
>>> tree
{'weight': tensor([[1., 1.]], device='cuda:0'), 'bias': tensor([0., 0.])}

# Flatten without specifying the namespace
>>> optree.tree_flatten(tree)  # `torch.Tensor`s are leaf nodes
([tensor([0., 0.]), tensor([[1., 1.]], device='cuda:0')], PyTreeSpec({'bias': *, 'weight': *}))

# Flatten with the namespace
>>> leaves, treespec = optree.tree_flatten(tree, namespace='torch2numpy')
>>> leaves, treespec
(
    [array([0., 0.], dtype=float32), array([[1., 1.]], dtype=float32)],
    PyTreeSpec(
        {
            'bias': CustomTreeNode(Tensor[{'dtype': torch.float32, 'device': device(type='cpu'), 'requires_grad': False}], [*]),
            'weight': CustomTreeNode(Tensor[{'dtype': torch.float32, 'device': device(type='cuda', index=0), 'requires_grad': False}], [*])
        },
        namespace='torch2numpy'
    )
)

# `entries` are not defined and use `range(len(children))`
>>> optree.tree_paths(tree, namespace='torch2numpy')
[('bias', 0), ('weight', 0)]

# Unflatten back to a copy of the original object
>>> optree.tree_unflatten(treespec, leaves)
{'weight': tensor([[1., 1.]], device='cuda:0'), 'bias': tensor([0., 0.])}

Users can also extend the pytree registry by decorating the custom class and defining an instance method tree_flatten and a class method tree_unflatten.

from collections import UserDict

@optree.register_pytree_node_class(namespace='mydict')
class MyDict(UserDict):
    def tree_flatten(self):  # -> (children, metadata, entries)
        reversed_keys = sorted(self.keys(), reverse=True)
        return (
            [self[key] for key in reversed_keys],  # children
            reversed_keys,  # metadata
            reversed_keys,  # entries
        )

    @classmethod
    def tree_unflatten(cls, metadata, children):
        return cls(zip(metadata, children))
>>> tree = MyDict(b=4, a=(2, 3), c=MyDict({'d': 5, 'f': 6}))

# Flatten without specifying the namespace
>>> optree.tree_flatten_with_path(tree)  # `MyDict`s are leaf nodes
(
    [()],
    [MyDict(b=4, a=(2, 3), c=MyDict({'d': 5, 'f': 6}))],
    PyTreeSpec(*)
)

# Flatten with the namespace
>>> optree.tree_flatten_with_path(tree, namespace='mydict')
(
    [('c', 'f'), ('c', 'd'), ('b',), ('a', 0), ('a', 1)],
    [6, 5, 4, 2, 3],
    PyTreeSpec(
        CustomTreeNode(MyDict[['c', 'b', 'a']], [CustomTreeNode(MyDict[['f', 'd']], [*, *]), *, (*, *)]),
        namespace='mydict'
    )
)

Notes about the PyTree Type Registry

There are several key attributes of the pytree type registry:

  1. The type registry is per-interpreter-dependent. This means registering a custom type in the registry affects all modules that use OpTree.

[!WARNING] For safety reasons, a namespace must be specified while registering a custom type. It is used to isolate the behavior of flattening and unflattening a pytree node type. This is to prevent accidental collisions between different libraries that may register the same type.

  1. The elements in the type registry are immutable. Users can neither register the same type twice in the same namespace (i.e., update the type registry), nor remove a type from the type registry. To update the behavior of an already registered type, simply register it again with another namespace.

  2. Users cannot modify the behavior of already registered built-in types listed in Built-in PyTree Node Types, such as key order sorting for dict and collections.defaultdict.

  3. Inherited subclasses are not implicitly registered. The registration lookup uses type(obj) is registered_type rather than isinstance(obj, registered_type). Users need to register the subclasses explicitly. To register all subclasses, it is easy to implement with metaclass or __init_subclass__, for example:

    from collections import UserDict
    
    @optree.register_pytree_node_class(namespace='mydict')
    class MyDict(UserDict):
        def __init_subclass__(cls):  # define this in the base class
            super().__init_subclass__()
            # Register a subclass to namespace 'mydict'
            optree.register_pytree_node_class(cls, namespace='mydict')
    
        def tree_flatten(self):  # -> (children, metadata, entries)
            reversed_keys = sorted(self.keys(), reverse=True)
            return (
                [self[key] for key in reversed_keys],  # children
                reversed_keys,  # metadata
                reversed_keys,  # entries
            )
    
        @classmethod
        def tree_unflatten(cls, metadata, children):
            return cls(zip(metadata, children))
    
    # Subclasses will be automatically registered in namespace 'mydict'
    class MyAnotherDict(MyDict):
        pass
    
    >>> tree = MyDict(b=4, a=(2, 3), c=MyAnotherDict({'d': 5, 'f': 6}))
    >>> optree.tree_flatten_with_path(tree, namespace='mydict')
    (
        [('c', 'f'), ('c', 'd'), ('b',), ('a', 0), ('a', 1)],
        [6, 5, 4, 2, 3],
        PyTreeSpec(
            CustomTreeNode(MyDict[['c', 'b', 'a']], [CustomTreeNode(MyAnotherDict[['f', 'd']], [*, *]), *, (*, *)]),
            namespace='mydict'
        )
    )
    
  4. Be careful about the potential infinite recursion of the custom flatten function. The returned children from the custom flatten function are considered subtrees. They will be further flattened recursively. The children can have the same type as the current node. Users must design their termination condition carefully.

    import numpy as np
    import torch
    
    optree.register_pytree_node(
        np.ndarray,
        # Children are nest lists of Python objects
        lambda array: (np.atleast_1d(array).tolist(), array.ndim == 0),
        lambda scalar, rows: np.asarray(rows) if not scalar else np.asarray(rows[0]),
        namespace='numpy1',
    )
    
    optree.register_pytree_node(
        np.ndarray,
        # Children are Python objects
        lambda array: (
            list(array.ravel()),  # list(1DArray[T]) -> List[T]
            dict(shape=array.shape, dtype=array.dtype)
        ),
        lambda metadata, children: np.asarray(children, dtype=metadata['dtype']).reshape(metadata['shape']),
        namespace='numpy2',
    )
    
    optree.register_pytree_node(
        np.ndarray,
        # Returns a list of `np.ndarray`s without termination condition
        lambda array: ([array.ravel()], array.dtype),
        lambda shape, children: children[0].reshape(shape),
        namespace='numpy3',
    )
    
    optree.register_pytree_node(
        torch.Tensor,
        # Children are nest lists of Python objects
        lambda tensor: (torch.atleast_1d(tensor).tolist(), tensor.ndim == 0),
        lambda scalar, rows: torch.tensor(rows) if not scalar else torch.tensor(rows[0])),
        namespace='torch1',
    )
    
    optree.register_pytree_node(
        torch.Tensor,
        # Returns a list of `torch.Tensor`s without termination condition
        lambda tensor: (
            list(tensor.view(-1)),  # list(1DTensor[T]) -> List[0DTensor[T]] (STILL TENSORS!)
            tensor.shape
        ),
        lambda shape, children: torch.stack(children).reshape(shape),
        namespace='torch2',
    )
    
    >>> optree.tree_flatten(np.arange(9).reshape(3, 3), namespace='numpy1')
    (
        [0, 1, 2, 3, 4, 5, 6, 7, 8],
        PyTreeSpec(
            CustomTreeNode(ndarray[False], [[*, *, *], [*, *, *], [*, *, *]]),
            namespace='numpy1'
        )
    )
    # Implicitly casts `float`s to `np.float64`
    >>> optree.tree_map(lambda x: x + 1.5, np.arange(9).reshape(3, 3), namespace='numpy1')
    array([[1.5, 2.5, 3.5],
           [4.5, 5.5, 6.5],
           [7.5, 8.5, 9.5]])
    
    >>> optree.tree_flatten(np.arange(9).reshape(3, 3), namespace='numpy2')
    (
        [0, 1, 2, 3, 4, 5, 6, 7, 8],
        PyTreeSpec(
            CustomTreeNode(ndarray[{'shape': (3, 3), 'dtype': dtype('int64')}], [*, *, *, *, *, *, *, *, *]),
            namespace='numpy2'
        )
    )
    # Explicitly casts `float`s to `np.int64`
    >>> optree.tree_map(lambda x: x + 1.5, np.arange(9).reshape(3, 3), namespace='numpy2')
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    
    # Children are also `np.ndarray`s, recurse without termination condition.
    >>> optree.tree_flatten(np.arange(9).reshape(3, 3), namespace='numpy3')
    Traceback (most recent call last):
        ...
    RecursionError: Maximum recursion depth exceeded during flattening the tree.
    
    >>> optree.tree_flatten(torch.arange(9).reshape(3, 3), namespace='torch1')
    (
        [0, 1, 2, 3, 4, 5, 6, 7, 8],
        PyTreeSpec(
            CustomTreeNode(Tensor[False], [[*, *, *], [*, *, *], [*, *, *]]),
            namespace='torch1'
        )
    )
    # Implicitly casts `float`s to `torch.float32`
    >>> optree.tree_map(lambda x: x + 1.5, torch.arange(9).reshape(3, 3), namespace='torch1')
    tensor([[1.5000, 2.5000, 3.5000],
            [4.5000, 5.5000, 6.5000],
            [7.5000, 8.5000, 9.5000]])
    
    # Children are also `torch.Tensor`s, recurse without termination condition.
    >>> optree.tree_flatten(torch.arange(9).reshape(3, 3), namespace='torch2')
    Traceback (most recent call last):
        ...
    RecursionError: Maximum recursion depth exceeded during flattening the tree.
    

None is Non-leaf Node vs. None is Leaf

The None object is a special object in the Python language. It serves some of the same purposes as null (a pointer does not point to anything) in other programming languages, which denotes a variable is empty or marks default parameters. However, the None object is a singleton object rather than a pointer. It may also serve as a sentinel value. In addition, if a function has returned without any return value or the return statement is omitted, the function will also implicitly return the None object.

By default, the None object is considered a non-leaf node in the tree with arity 0, i.e., a non-leaf node that has no children. This is like the behavior of an empty tuple. While flattening a tree, it will remain in the tree structure definitions rather than in the leaves list.

>>> tree = {'b': (2, [3, 4]), 'a': 1, 'c': None, 'd': 5}
>>> optree.tree_flatten(tree)
([1, 2, 3, 4, 5], PyTreeSpec({'a': *, 'b': (*, [*, *]), 'c': None, 'd': *}))
>>> optree.tree_flatten(tree, none_is_leaf=True)
([1, 2, 3, 4, None, 5], PyTreeSpec({'a': *, 'b': (*, [*, *]), 'c': *, 'd': *}, NoneIsLeaf))
>>> optree.tree_flatten(1)
([1], PyTreeSpec(*))
>>> optree.tree_flatten(None)
([], PyTreeSpec(None))
>>> optree.tree_flatten(None, none_is_leaf=True)
([None], PyTreeSpec(*, NoneIsLeaf))

OpTree provides a keyword argument none_is_leaf to determine whether to consider the None object as a leaf, like other opaque objects. If none_is_leaf=True, the None object will place in the leaves list. Otherwise, the None object will remain in the tree specification (structure).

>>> import torch

>>> linear = torch.nn.Linear(in_features=3, out_features=2, bias=False)
>>> linear._parameters  # a container has None
OrderedDict([
    ('weight', Parameter containing:
               tensor([[-0.6677,  0.5209,  0.3295],
                       [-0.4876, -0.3142,  0.1785]], requires_grad=True)),
    ('bias', None)
])

>>> optree.tree_map(torch.zeros_like, linear._parameters)
OrderedDict([
    ('weight', tensor([[0., 0., 0.],
                       [0., 0., 0.]])),
    ('bias', None)
])

>>> optree.tree_map(torch.zeros_like, linear._parameters, none_is_leaf=True)
Traceback (most recent call last):
    ...
TypeError: zeros_like(): argument 'input' (position 1) must be Tensor, not NoneType

>>> optree.tree_map(lambda t: torch.zeros_like(t) if t is not None else 0, linear._parameters, none_is_leaf=True)
OrderedDict([
    ('weight', tensor([[0., 0., 0.],
                       [0., 0., 0.]])),
    ('bias', 0)
])

Key Ordering for Dictionaries

The built-in Python dictionary (i.e., builtins.dict) is an unordered mapping that holds the keys and values. The leaves of a dictionary are the values. Although since Python 3.6, the built-in dictionary is insertion ordered (PEP 468). The dictionary equality operator (==) does not check for key ordering. To ensure referential transparency that "equal dict" implies "equal ordering of leaves", the order of values of the dictionary is sorted by the keys. This behavior is also applied to collections.defaultdict.

>>> optree.tree_flatten({'a': [1, 2], 'b': [3]})
([1, 2, 3], PyTreeSpec({'a': [*, *], 'b': [*]}))
>>> optree.tree_flatten({'b': [3], 'a': [1, 2]})
([1, 2, 3], PyTreeSpec({'a': [*, *], 'b': [*]}))

If users want to keep the values in the insertion order in pytree traversal, they should use collections.OrderedDict, which will take the order of keys under consideration:

>>> OrderedDict([('a', [1, 2]), ('b', [3])]) == OrderedDict([('b', [3]), ('a', [1, 2])])
False
>>> optree.tree_flatten(OrderedDict([('a', [1, 2]), ('b', [3])]))
([1, 2, 3], PyTreeSpec(OrderedDict([('a', [*, *]), ('b', [*])])))
>>> optree.tree_flatten(OrderedDict([('b', [3]), ('a', [1, 2])]))
([3, 1, 2], PyTreeSpec(OrderedDict([('b', [*]), ('a', [*, *])])))

Since OpTree v0.9.0, the key order of the reconstructed output dictionaries from tree_unflatten is guaranteed to be consistent with the key order of the input dictionaries in tree_flatten.

>>> leaves, treespec = optree.tree_flatten({'b': [3], 'a': [1, 2]})
>>> leaves, treespec
([1, 2, 3], PyTreeSpec({'a': [*, *], 'b': [*]}))
>>> optree.tree_unflatten(treespec, leaves)
{'b': [3], 'a': [1, 2]}
>>> optree.tree_map(lambda x: x, {'b': [3], 'a': [1, 2]})
{'b': [3], 'a': [1, 2]}
>>> optree.tree_map(lambda x: x + 1, {'b': [3], 'a': [1, 2]})
{'b': [4], 'a': [2, 3]}

This property is also preserved during serialization/deserialization.

>>> leaves, treespec = optree.tree_flatten({'b': [3], 'a': [1, 2]})
>>> leaves, treespec
([1, 2, 3], PyTreeSpec({'a': [*, *], 'b': [*]}))
>>> restored_treespec = pickle.loads(pickle.dumps(treespec))
>>> optree.tree_unflatten(treespec, leaves)
{'b': [3], 'a': [1, 2]}
>>> optree.tree_unflatten(restored_treespec, leaves)
{'b': [3], 'a': [1, 2]}

[!NOTE] Note that there are no restrictions on the dict to require the keys to be comparable (sortable). There can be multiple types of keys in the dictionary. The keys are sorted in ascending order by key=lambda k: k first if capable otherwise fallback to key=lambda k: (f'{k.__class__.__module__}.{k.__class__.__qualname__}', k). This handles most cases.

>>> sorted({1: 2, 1.5: 1}.keys())
[1, 1.5]
>>> sorted({'a': 3, 1: 2, 1.5: 1}.keys())
Traceback (most recent call last):
    ...
TypeError: '<' not supported between instances of 'int' and 'str'
>>> sorted({'a': 3, 1: 2, 1.5: 1}.keys(), key=lambda k: (f'{k.__class__.__module__}.{k.__class__.__qualname__}', k))
[1.5, 1, 'a']

Benchmark

We benchmark the performance of:

  • tree flatten
  • tree unflatten
  • tree copy (i.e., unflatten(flatten(...)))
  • tree map

compared with the following libraries:

Average Time Cost (↓) OpTree (v0.9.0) JAX XLA (v0.4.6) PyTorch (v2.0.0) DM-Tree (v0.1.8)
Tree Flatten x1.00 2.33 22.05 1.12
Tree UnFlatten x1.00 2.69 4.28 16.23
Tree Flatten with Path x1.00 16.16 Not Supported 27.59
Tree Copy x1.00 2.56 9.97 11.02
Tree Map x1.00 2.56 9.58 10.62
Tree Map (nargs) x1.00 2.89 Not Supported 31.33
Tree Map with Path x1.00 7.23 Not Supported 19.66
Tree Map with Path (nargs) x1.00 6.56 Not Supported 29.61

All results are reported on a workstation with an AMD Ryzen 9 5950X CPU @ 4.45GHz in an isolated virtual environment with Python 3.10.9. Run with the following commands:

conda create --name optree-benchmark anaconda::python=3.10 --yes --no-default-packages
conda activate optree-benchmark
python3 -m pip install --editable '.[benchmark]' --extra-index-url https://download.pytorch.org/whl/cpu
python3 benchmark.py --number=10000 --repeat=5

The test inputs are nested containers (i.e., pytrees) extracted from torch.nn.Module objects. They are:

tiny_mlp = nn.Sequential(
    nn.Linear(1, 1, bias=True),
    nn.BatchNorm1d(1, affine=True, track_running_stats=True),
    nn.ReLU(),
    nn.Linear(1, 1, bias=False),
    nn.Sigmoid(),
)

and AlexNet, ResNet18, ResNet34, ResNet50, ResNet101, ResNet152, VisionTransformerH14 (ViT-H/14), and SwinTransformerB (Swin-B) from torchvsion. Please refer to benchmark.py for more details.

Tree Flatten

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 29.70 71.06 583.66 31.32 2.39 19.65 1.05
AlexNet 188 103.92 262.56 2304.36 119.61 2.53 22.17 1.15
ResNet18 698 368.06 852.69 8440.31 420.43 2.32 22.93 1.14
ResNet34 1242 644.96 1461.55 14498.81 712.81 2.27 22.48 1.11
ResNet50 1702 919.95 2080.58 20995.96 1006.42 2.26 22.82 1.09
ResNet101 3317 1806.36 3996.90 40314.12 1955.48 2.21 22.32 1.08
ResNet152 4932 2656.92 5812.38 57775.53 2826.92 2.19 21.75 1.06
ViT-H/14 3420 1863.50 4418.24 41334.64 2128.71 2.37 22.18 1.14
Swin-B 2881 1631.06 3944.13 36131.54 2032.77 2.42 22.15 1.25
Average 2.33 22.05 1.12

Tree UnFlatten

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 55.13 152.07 231.94 940.11 2.76 4.21 17.05
AlexNet 188 226.29 678.29 972.90 4195.04 3.00 4.30 18.54
ResNet18 698 766.54 1953.26 3137.86 12049.88 2.55 4.09 15.72
ResNet34 1242 1309.22 3526.12 5759.16 20966.75 2.69 4.40 16.01
ResNet50 1702 1914.96 5002.83 8369.43 29597.10 2.61 4.37 15.46
ResNet101 3317 3672.61 9633.29 15683.16 57240.20 2.62 4.27 15.59
ResNet152 4932 5407.58 13970.88 23074.68 82072.54 2.58 4.27 15.18
ViT-H/14 3420 4013.18 11146.31 17633.07 66723.58 2.78 4.39 16.63
Swin-B 2881 3595.34 9505.31 15054.88 57310.03 2.64 4.19 15.94
Average 2.69 4.28 16.23

Tree Flatten with Path

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 36.49 543.67 N/A 919.13 14.90 N/A 25.19
AlexNet 188 115.44 2185.21 N/A 3752.11 18.93 N/A 32.50
ResNet18 698 431.84 7106.55 N/A 12286.70 16.46 N/A 28.45
ResNet34 1242 845.61 13431.99 N/A 22860.48 15.88 N/A 27.03
ResNet50 1702 1166.27 18426.52 N/A 31225.05 15.80 N/A 26.77
ResNet101 3317 2312.77 34770.49 N/A 59346.86 15.03 N/A 25.66
ResNet152 4932 3304.74 50557.25 N/A 85847.91 15.30 N/A 25.98
ViT-H/14 3420 2235.25 37473.53 N/A 64105.24 16.76 N/A 28.68
Swin-B 2881 1970.25 32205.83 N/A 55177.50 16.35 N/A 28.01
Average 16.16 N/A 27.59

Tree Copy

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 89.81 232.26 845.20 981.48 2.59 9.41 10.93
AlexNet 188 334.58 959.32 3360.46 4316.05 2.87 10.04 12.90
ResNet18 698 1128.11 2840.71 11471.07 12297.07 2.52 10.17 10.90
ResNet34 1242 2160.57 5333.10 20563.06 21901.91 2.47 9.52 10.14
ResNet50 1702 2746.84 6823.88 29705.99 28927.88 2.48 10.81 10.53
ResNet101 3317 5762.05 13481.45 56968.78 60115.93 2.34 9.89 10.43
ResNet152 4932 8151.21 20805.61 81024.06 84079.57 2.55 9.94 10.31
ViT-H/14 3420 5963.61 15665.91 59813.52 68377.82 2.63 10.03 11.47
Swin-B 2881 5401.59 14255.33 53361.77 62317.07 2.64 9.88 11.54
Average 2.56 9.97 11.02

Tree Map

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 95.13 243.86 867.34 1026.99 2.56 9.12 10.80
AlexNet 188 348.44 987.57 3398.32 4354.81 2.83 9.75 12.50
ResNet18 698 1190.62 2982.66 11719.94 12559.01 2.51 9.84 10.55
ResNet34 1242 2205.87 5417.60 20935.72 22308.51 2.46 9.49 10.11
ResNet50 1702 3128.48 7579.55 30372.71 31638.67 2.42 9.71 10.11
ResNet101 3317 6173.05 14846.57 59167.85 60245.42 2.41 9.58 9.76
ResNet152 4932 8641.22 22000.74 84018.65 86182.21 2.55 9.72 9.97
ViT-H/14 3420 6211.79 17077.49 59790.25 69763.86 2.75 9.63 11.23
Swin-B 2881 5673.66 14339.69 53309.17 59764.61 2.53 9.40 10.53
Average 2.56 9.58 10.62

Tree Map (nargs)

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 137.06 389.96 N/A 3908.77 2.85 N/A 28.52
AlexNet 188 467.24 1496.96 N/A 15395.13 3.20 N/A 32.95
ResNet18 698 1603.79 4534.01 N/A 50323.76 2.83 N/A 31.38
ResNet34 1242 2907.64 8435.33 N/A 90389.23 2.90 N/A 31.09
ResNet50 1702 4183.77 11382.51 N/A 121777.01 2.72 N/A 29.11
ResNet101 3317 7721.13 22247.85 N/A 238755.17 2.88 N/A 30.92
ResNet152 4932 11508.05 31429.39 N/A 360257.74 2.73 N/A 31.30
ViT-H/14 3420 8294.20 24524.86 N/A 270514.87 2.96 N/A 32.61
Swin-B 2881 7074.62 20854.80 N/A 241120.41 2.95 N/A 34.08
Average 2.89 N/A 31.33

Tree Map with Path

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 109.82 778.30 N/A 2186.40 7.09 N/A 19.91
AlexNet 188 365.16 2939.36 N/A 8355.37 8.05 N/A 22.88
ResNet18 698 1308.26 9529.58 N/A 25758.24 7.28 N/A 19.69
ResNet34 1242 2527.21 18084.89 N/A 45942.32 7.16 N/A 18.18
ResNet50 1702 3226.03 22935.53 N/A 61275.34 7.11 N/A 18.99
ResNet101 3317 6663.52 46878.89 N/A 126642.14 7.04 N/A 19.01
ResNet152 4932 9378.19 66136.44 N/A 176981.01 7.05 N/A 18.87
ViT-H/14 3420 7033.69 50418.37 N/A 142508.11 7.17 N/A 20.26
Swin-B 2881 6078.15 43173.22 N/A 116612.71 7.10 N/A 19.19
Average 7.23 N/A 19.66

Tree Map with Path (nargs)

Module Nodes OpTree (μs) JAX XLA (μs) PyTorch (μs) DM-Tree (μs) Speedup (J / O) Speedup (P / O) Speedup (D / O)
TinyMLP 53 146.05 917.00 N/A 3940.61 6.28 N/A 26.98
AlexNet 188 489.27 3560.76 N/A 15434.71 7.28 N/A 31.55
ResNet18 698 1712.79 11171.44 N/A 50219.86 6.52 N/A 29.32
ResNet34 1242 3112.83 21024.58 N/A 95505.71 6.75 N/A 30.68
ResNet50 1702 4220.70 26600.82 N/A 121897.57 6.30 N/A 28.88
ResNet101 3317 8631.34 54372.37 N/A 236555.54 6.30 N/A 27.41
ResNet152 4932 12710.49 77643.13 N/A 353600.32 6.11 N/A 27.82
ViT-H/14 3420 8753.09 58712.71 N/A 286365.36 6.71 N/A 32.72
Swin-B 2881 7359.29 50112.23 N/A 228866.66 6.81 N/A 31.10
Average 6.56 N/A 29.61

Changelog

See CHANGELOG.md.


License

OpTree is released under the Apache License 2.0.

OpTree is heavily based on JAX's implementation of the PyTree utility, with deep refactoring and several improvements. The original licenses can be found at JAX's Apache License 2.0 and Tensorflow's Apache License 2.0.

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

optree-0.11.0.tar.gz (123.1 kB view details)

Uploaded Source

Built Distributions

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

optree-0.11.0-cp312-cp312-win_arm64.whl (241.7 kB view details)

Uploaded CPython 3.12Windows ARM64

optree-0.11.0-cp312-cp312-win_amd64.whl (241.7 kB view details)

Uploaded CPython 3.12Windows x86-64

optree-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (308.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

optree-0.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (283.8 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

optree-0.11.0-cp312-cp312-macosx_11_0_arm64.whl (276.7 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

optree-0.11.0-cp312-cp312-macosx_10_9_x86_64.whl (300.8 kB view details)

Uploaded CPython 3.12macOS 10.9+ x86-64

optree-0.11.0-cp312-cp312-macosx_10_9_universal2.whl (519.3 kB view details)

Uploaded CPython 3.12macOS 10.9+ universal2 (ARM64, x86-64)

optree-0.11.0-cp311-cp311-win_arm64.whl (245.0 kB view details)

Uploaded CPython 3.11Windows ARM64

optree-0.11.0-cp311-cp311-win_amd64.whl (245.0 kB view details)

Uploaded CPython 3.11Windows x86-64

optree-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (312.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

optree-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (285.8 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

optree-0.11.0-cp311-cp311-macosx_11_0_arm64.whl (274.7 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

optree-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl (296.6 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

optree-0.11.0-cp311-cp311-macosx_10_9_universal2.whl (513.0 kB view details)

Uploaded CPython 3.11macOS 10.9+ universal2 (ARM64, x86-64)

optree-0.11.0-cp310-cp310-win_arm64.whl (243.8 kB view details)

Uploaded CPython 3.10Windows ARM64

optree-0.11.0-cp310-cp310-win_amd64.whl (243.8 kB view details)

Uploaded CPython 3.10Windows x86-64

optree-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (311.2 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

optree-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (284.5 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

optree-0.11.0-cp310-cp310-macosx_11_0_arm64.whl (273.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

optree-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl (295.1 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

optree-0.11.0-cp310-cp310-macosx_10_9_universal2.whl (510.3 kB view details)

Uploaded CPython 3.10macOS 10.9+ universal2 (ARM64, x86-64)

optree-0.11.0-cp39-cp39-win_arm64.whl (240.0 kB view details)

Uploaded CPython 3.9Windows ARM64

optree-0.11.0-cp39-cp39-win_amd64.whl (240.0 kB view details)

Uploaded CPython 3.9Windows x86-64

optree-0.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (311.9 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

optree-0.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (285.3 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

optree-0.11.0-cp39-cp39-macosx_11_0_arm64.whl (273.4 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

optree-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl (295.2 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

optree-0.11.0-cp39-cp39-macosx_10_9_universal2.whl (510.4 kB view details)

Uploaded CPython 3.9macOS 10.9+ universal2 (ARM64, x86-64)

optree-0.11.0-cp38-cp38-win_amd64.whl (244.0 kB view details)

Uploaded CPython 3.8Windows x86-64

optree-0.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (311.1 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

optree-0.11.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (284.7 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ ARM64

optree-0.11.0-cp38-cp38-macosx_11_0_arm64.whl (273.2 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

optree-0.11.0-cp38-cp38-macosx_10_9_x86_64.whl (295.1 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

optree-0.11.0-cp38-cp38-macosx_10_9_universal2.whl (510.1 kB view details)

Uploaded CPython 3.8macOS 10.9+ universal2 (ARM64, x86-64)

optree-0.11.0-cp37-cp37m-win_amd64.whl (240.1 kB view details)

Uploaded CPython 3.7mWindows x86-64

optree-0.11.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (318.7 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.17+ x86-64

optree-0.11.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (293.7 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.17+ ARM64

optree-0.11.0-cp37-cp37m-macosx_10_9_x86_64.whl (289.0 kB view details)

Uploaded CPython 3.7mmacOS 10.9+ x86-64

File details

Details for the file optree-0.11.0.tar.gz.

File metadata

  • Download URL: optree-0.11.0.tar.gz
  • Upload date:
  • Size: 123.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0.tar.gz
Algorithm Hash digest
SHA256 8e6a46e95c3ea8546055087d6fe52a1dcd56de5182365f1469106cc72cdf3307
MD5 2c808bc528c6adeab12d8df55f57fd26
BLAKE2b-256 489d384c007ba68f0a0a7ea53f32893d877d5a3ab3f14d5a318e68af11149749

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-win_arm64.whl.

File metadata

  • Download URL: optree-0.11.0-cp312-cp312-win_arm64.whl
  • Upload date:
  • Size: 241.7 kB
  • Tags: CPython 3.12, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 26b1230f9b75b579923a4f837c7c13db8b8d815cf68ce5af31dda5d818a877b2
MD5 4b5ae38f86561ffe412e66396762348e
BLAKE2b-256 7451d9dbe7e7b21618bbaaaa0be604ee0b949c0f892e4f226ea4a7325cbf53fd

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: optree-0.11.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 241.7 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 ee208f0bec6436085a9fa3ae98af54bfcb8822086894fc1ade283e80a6f11fd7
MD5 036c1251e4c1b5d50e3bb98f410e5c96
BLAKE2b-256 8dd68fbe48f9a022cd58926be69a5e8a6c2b96b7206f2bd722116b37d334bb50

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5e5df0e8aaca124cc1ffca311786cc909810f3c046de090729cdafbf910082f8
MD5 25660bdf1b4c0b22f53423dcdadab59d
BLAKE2b-256 0da83ab0db4e460a79ba9d95748b76950db1e2b45d96abaea91c096dde289ca9

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0db6968394096223881053dffdcaf2b8e220fd85db904f14aa931e4dc422c046
MD5 4877618356319a6e3d9cdd5dbccb0611
BLAKE2b-256 1d6b31e513bed36977ff4145df0c9c2e08017b122954df06adbc3bfcdb4f1944

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 738e8bf4158e9c11cd051d89c2e453aeacf80ff8719ebc3251069015646554d0
MD5 69ed45718244fb708f91dec5c3299f7b
BLAKE2b-256 a4694601d52757167698fbf6718680b51feadc9dfaaf8569759e1e3fa14823b6

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 64c2e00fe508f50a42c50838df0d1f5be0dce5b4bef2373db8ad72b860211015
MD5 6de1538df375c86acc82103e9bdfa6d3
BLAKE2b-256 fae46dcb982b34f76a310c1e93ef0df27600cc1d8b0d016fe9daf7a726933b71

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp312-cp312-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 9bf322ad14f907ad4660ca286e731e750546d54934a94cc5ba7efe8860c60ab4
MD5 2fb56917957b19ac0e8b9fa98777a75c
BLAKE2b-256 8aa40f7292343e7adf6497b358f8a64cd95fb89b61346fde96a10b7e2760f4a0

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-win_arm64.whl.

File metadata

  • Download URL: optree-0.11.0-cp311-cp311-win_arm64.whl
  • Upload date:
  • Size: 245.0 kB
  • Tags: CPython 3.11, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 d666099a78f7bf31bf3a520d6871ddcae65484bcff095fc4271a391553b09c75
MD5 5ccbeb54644a51de702b637b890a9dd5
BLAKE2b-256 84b24135407f40aedd4c5b470e0868b72d610432dbaecdd267c7f335cca07c58

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: optree-0.11.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 245.0 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 a64df43fce2d8eeafd7db6e27447c56b3fa64842df847819684b3b1cc254c016
MD5 c5c906fca8e7d95255af45854242b709
BLAKE2b-256 8fdbe05a35451d4ba30fdc65ef168dfdc68a6939ea6afdc0101e3e77f97e1547

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bc17f9d085cd75a2de4f299a9c5e3c3520138eac7596061e581230b03862b44d
MD5 23a442cbd0c723ca1d71bf9d227b579d
BLAKE2b-256 3ceaefd59fc3cec0d0d7f953b956ef881ca4b972696c8f4261cbca23c636b908

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5e250144eacdd5813dec0b18d91df0229197e3be402db42fd8e254ec90ea343d
MD5 01453ca6b7454ca8fc516b6f638a2af5
BLAKE2b-256 07eb951ddc799ace6006164bc5472e7181a8465afb811aee47dd081c4151af81

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 39bed744a61e2f795e172d2853779ac59b8dea236982dc160ea22063afc99ca3
MD5 37cbd1e1d7e058ff82a7d199dc66bff1
BLAKE2b-256 ccb833127d52de868d2aabc14ec6f53cb2dffafd14c5c708f50d171552a3a451

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 6e8c3757088cd7fce666f2a5e031b65d7898e210452380d2657c0fc0a7ec9932
MD5 4ec496ceefeb33aa14f7abc6de3df994
BLAKE2b-256 eba7b99e2a5f3e73e6fcdaa0a936577b993e7f6fe2c87410f745d9180aa8147d

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp311-cp311-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 a5f37bcfe4e363e3bb8d36c5698fb829546956b2fe88951994387162a1859625
MD5 18e65cdcd5a155f42c0576a5bd73bd45
BLAKE2b-256 f0136308b934422b3af2c24f9e1f81bdc5738199a009b37c84bd5056f4509e66

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-win_arm64.whl.

File metadata

  • Download URL: optree-0.11.0-cp310-cp310-win_arm64.whl
  • Upload date:
  • Size: 243.8 kB
  • Tags: CPython 3.10, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 31d444684ebd8c9f09a3d806fb3277843138ef9952b7a2954908e440e3b22519
MD5 f0038571a4e9a0e0a0dfcb7a4cfa595c
BLAKE2b-256 7db9350dcd19bb22c43f7bad6db64842ae3057f7ceb87425be3b997fae62c2d3

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: optree-0.11.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 243.8 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 a91840f9d45e7c01f151ba1815ae32b4c3c21e4290298772ee4b13314f729856
MD5 7220a4b233c49cd8ab84451095f5ebb5
BLAKE2b-256 c70b8a3e5da51d7d25ca8bc08c257fb448259a2abd66f62b47407d8c32846826

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 228b97e8c991739b10c8548c118747ba32ee765f88236342e492bf9648afc0bc
MD5 dd7aee6b65eb37cf41bc2f09b329a303
BLAKE2b-256 0b1bafe635bae61fedc09fc702e7162fe7f31f437c872f827d22b04fa4861c29

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 979ffc2b96f16595c219fb7a89597dd2fa00ac47a3b411fdcf8ae6821da52290
MD5 2ffda33d4d36604481129ba4b4fe80c5
BLAKE2b-256 d7a5ef3ddd59c8f90ae609299d49635ac0602f410c74a667469755fab52cfb6c

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0df9a3923725aabb112ec7f10c74fa96b6c640da1cd30e7bc62fd4b03ef02875
MD5 28dd979a13e79e8a1c6d08f87cb81b8d
BLAKE2b-256 3e4afadc346b3c83f0eb3b2cd91cf5ccad2851ac3411c2e6d33c9cfd54b3659a

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 f53951bfb640417558568284a8949d67bcdbf21fa0113107e20bd9403aa20b2b
MD5 3a561bb9f0df5ef79528a58d24f69119
BLAKE2b-256 5ea28eca362c33207cc6832088414fdeec4afa7953f06c6d7182c7a9ecb00da0

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp310-cp310-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 fa9ed745d4cbac5e15df70339b30867ba033542b87f7b734f4cacae5ec73ba00
MD5 74df34fa627b6a246e1516f926f6deea
BLAKE2b-256 af6e68277472eb2407370b499a02bfed24649a9b861e6c3e81ec71847ac9e638

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-win_arm64.whl.

File metadata

  • Download URL: optree-0.11.0-cp39-cp39-win_arm64.whl
  • Upload date:
  • Size: 240.0 kB
  • Tags: CPython 3.9, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 9d9d644e5448db9f32e2497487aca3bb2d3f92cbb50429a411ccda3f1f0968f3
MD5 9b85ca7ed03f189eb14fe5be5595627b
BLAKE2b-256 e28a5b7c2dcd3b130de524664746a1ae0df7ceb01de258862f504cd0489f5542

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: optree-0.11.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 240.0 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 b26ac807d8993b7e43081b4b7bbb0378b4e5f3e6525daf923c470bc176cc3327
MD5 9ccbcf70a78fbd0ef65b9503f3cfa810
BLAKE2b-256 ee23617f6287dd589ad50d9a5f86e3110622fc013621f87f9bd80fd2ed6128e9

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b9d236bc1491a5e366921b95fecc05aa6ff55989a81f2242cd11121b82c24503
MD5 fe26ef55ea6673687ddecaaeba5f1baa
BLAKE2b-256 dc574ddcfd28f208d7ca02d96c375d8a5c1e84cc604464522c6c161ac63e30b5

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4144126dd3c2ece2d2dd1d5e0b39fb91adf1c46f660c2c5a2df7f80666989d5d
MD5 035f1cec4cbee03824a94e5b90a2b9c6
BLAKE2b-256 66d538cb9dd18e4e228bf3789e40dca51d8a3512c7d505e7ca49e1c06f0fb74b

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b8126d81ecb2c9e3554420834014ba343251f564c905ee3bef09d205b924b0c0
MD5 3fd493167ab2a23069e414aa2ce43196
BLAKE2b-256 5fd4e7db05dadaee0fed733f4c179b80539494d22f55e2b6d417fadeee9c1938

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 418850ceff364f51a6d81f32a1efd06a4e2d8df79a162e892685bc20c0aedd72
MD5 acfcb7e6971ffa86387717dd0d4437ad
BLAKE2b-256 071d0315c4c462aac13f8b15063f135294957875c07bc24573c10ab4f5d8a53b

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 00a63f10d4a476e8e9aa2988daba9b2e88cb369c5aacc12545957d7d00bcd1a7
MD5 6ba8d771ba19e972ee26318b78eeb4bb
BLAKE2b-256 7b85b74f1739f8f868e519656b702a4bb15e0d76593988019afe9b732918741e

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: optree-0.11.0-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 244.0 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 162ed3ff2eb3f1c358e131e72c025f2b93d69b906e9057a811d014032ec71dc8
MD5 0e1dd1d0d37f02705330d2a4384362ae
BLAKE2b-256 296807fa07e56f3c938a8a7a1b59f49d6713a3508dfe0787c89a0c448dfb39ad

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b201a9405e250cf5770955863af2a236e382bdf5e4e086897ff03c41418c39da
MD5 d0e69d5d11358978621bada12adfcfe1
BLAKE2b-256 2d5dc573971771ed0660c182cbbd63cee01d812a5ebac79df4226b459b27c204

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2b3bb59324d635f2015bb3e237fd772b1fd548eee6cc80e008fbe0f092e9228d
MD5 5a2d5e74e74c5eba8ae9ac21dbf0f67c
BLAKE2b-256 452bb0738c5ceb752a62a8247606d57d61dacedc063c79d2fc21de4141a9995a

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3cdc9fac9888d9eff11128ccfc4d4c10309163e372f312f7942ecee8df3d7824
MD5 cb6710fed75fa3a2cb86068caa6e3ce5
BLAKE2b-256 0e5dddf0296689db85fa44cbafb01ea062e19b036d86910964e60d5dee16952d

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 2bc08fb9691f43afc3a01119dead6b823ce3d7239e42fc3e47d4028eed50a6a2
MD5 633fd1ab5685fa273d0ad80baa0fcf59
BLAKE2b-256 70bc7e15e33521c46ad3e81bcae29994e9fc4913efa0480b401a04e1776a4346

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp38-cp38-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 e2d47bd28eff690eb2f7432e490265a291b04d6d346cf7b586491b2e2337bf97
MD5 658c439b681ceda302a7a6df93c4f7e4
BLAKE2b-256 d3185b97c898d33d2a5f777d7c4c421aa774dbfede13fee3dfd64ad325776bd3

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: optree-0.11.0-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 240.1 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for optree-0.11.0-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 63e020a34b7168b5d0701a265c7c95b07984ff699d4894b20fa601282be88f20
MD5 37b4a0e992f2bc0ee5d72db449f1f4d1
BLAKE2b-256 2c6e866881dfd18e1336c7a09d4a8be9e83847aaa4e874db4e1468b4a2d018bb

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6a406eee5acd3fd4875fa44c3972d29ae6d4329e7296e9219986fe6ff8e92ea0
MD5 71f8a2d3163ee36afe445486173ef7bd
BLAKE2b-256 d8ac20d461bd9f32532d80bd26908e1f68088713dc648115ba8a778db015c300

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 234a4f8f97a1217f13390df7ac416771689749d9a1c8eda31bf8622cd333219e
MD5 7ed62cf6d7b1e852b2930f4e00d39298
BLAKE2b-256 2ae18cca3d55cd54d1e08455fe39e6558b748d67d2d14b7f3deeebf4b1fd5b51

See more details on using hashes here.

File details

Details for the file optree-0.11.0-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for optree-0.11.0-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 6cdd625dab2dff5374ff9c6792e8702fced8f0ea713ce959fc8f95499b5ecb2f
MD5 9f6055c131cdc91e855daa7b1e932e2c
BLAKE2b-256 cf13e01161e0dc18da2c401ee4180be502dcc5e1656c1f8534a014c33a143381

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