Skip to content

Commit

Permalink
[Doc] [lang] Cherrypick commits related to packed mode (#6765)
Browse files Browse the repository at this point in the history
### Brief Summary

Cherrypicks #6755 and #6753 into v1.3.0 release branch.

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
strongoier and pre-commit-ci[bot] authored Nov 30, 2022
1 parent 16244cc commit 67c0cd8
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 25 deletions.
26 changes: 6 additions & 20 deletions docs/lang/articles/basic/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ ti.root.dense(ti.ij, (M // 8, N // 8)).dense(ti.ij, (8, 8)).place(val)

where `M` and `N` are multiples of 8. We encourage you to try this out! The performance difference can be significant!

:::note

We highly recommend that you use power-of-two block size so that accelerated indexing with bitwise arithmetic and better memory address alignment can be enabled.

:::

## Manage memory occupancy

### Manual field allocation and destruction
Expand Down Expand Up @@ -358,23 +364,3 @@ fb2_snode_tree.destroy() # Destruction
```

Actually, the above demonstrated `ti.root` statements are implemented with `FieldsBuilder`, despite that `ti.root` has the capability to automatically manage memory allocations and recycling.

### Packed mode

By default, Taichi implicitly fits a field in a larger buffer with power-of-two dimensions. We take the power-of-two padding convention because it is widely adopted in computer graphics. The design enables fast indexing with bitwise arithmetic and better memory address alignment, while trading off memory occupations.

For example, a `(18, 65)` field is materialized with a `(32, 128)` buffer, which is acceptable. As field size grows, the padding strategy can be exaggeratedly unbearable: `(129, 6553600)` will be expanded to `(256, 6335600)`, which allocates considerable unused blank memory. Therefore, Taichi provides the optional packed mode to allocate buffer that tightly fits the requested field shape. It is especially useful when memory usage is a major concern.

To leverage the packed mode, specify `packed` in `ti.init()` argument:

```python
ti.init() # default: packed=False
a = ti.field(ti.i32, shape=(18, 65)) # padded to (32, 128)
```

```python
ti.init(packed=True)
a = ti.field(ti.i32, shape=(18, 65)) # no padding
```

You might observe mild performance regression with the packed mode due to more complex addressing and memory alignment. Therefore, the packed mode should be specified only when memory capacity is a major concern.
11 changes: 11 additions & 0 deletions python/taichi/lang/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,17 @@ def init(arch=None,
if require_version is not None:
check_require_version(require_version)

if "packed" in kwargs:
if kwargs["packed"] is True:
warnings.warn(
"Currently packed=True is the default setting and the switch will be removed in v1.4.0.",
DeprecationWarning)
else:
warnings.warn(
"The automatic padding mode (packed=False) will no longer exist in v1.4.0. The switch will "
"also be removed then. Make sure your code doesn't rely on it.",
DeprecationWarning)

if "default_up" in kwargs:
raise KeyError(
"'default_up' is always the unsigned type of 'default_ip'. Please set 'default_ip' instead."
Expand Down
8 changes: 3 additions & 5 deletions taichi/ir/snode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ SNode &SNode::create_node(std::vector<Axis> axes,
} else {
TI_WARN_IF(
packed && !bit::is_power_of_two(sizes[i]),
"Non-first division of an axis on a SNodeTree path should be a power "
"of two to achieve best performance:\n{} We plan to turn this "
"warning into an error at v1.4.0. If you do have a use case that "
"needs to violate this rule, please submit an issue to notify us.",
tb);
"Shape {} is detected on non-first division of axis {}:\n{} For "
"best performance, we recommend that you set it to a power of two.",
sizes[i], char('i' + ind), tb);
}
new_node.extractors[ind].activate(
bit::log2int(bit::least_pot_bound(sizes[i])));
Expand Down
18 changes: 18 additions & 0 deletions tests/python/test_deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,21 @@ def test_deprecate_metal_sparse():
"Dynamic SNode on metal backend is deprecated and removed in this release."
):
ti.root.dynamic(ti.i, 10)


def test_deprecated_packed_true():
with pytest.warns(
DeprecationWarning,
match=
"Currently packed=True is the default setting and the switch will be removed in v1.4.0."
):
ti.init(packed=True)


def test_deprecated_packed_false():
with pytest.warns(
DeprecationWarning,
match=
r"The automatic padding mode \(packed=False\) will no longer exist in v1.4.0. The switch will "
"also be removed then. Make sure your code doesn't rely on it."):
ti.init(packed=False)

0 comments on commit 67c0cd8

Please sign in to comment.