Structural nodes (SNodes)¶
After writing the computation code, the user needs to specify the internal data structure hierarchy. Specifying a data structure includes choices at both the macro level, dictating how the data structure components nest with each other and the way they represent sparsity, and the micro level, dictating how data are grouped together (e.g. structure of arrays vs. array of structures). Taichi provides Structural Nodes (SNodes) to compose the hierarchy and particular properties. These constructs and their semantics are listed below:
- dense: A fixed-length contiguous array.
- bitmasked: This is similar to dense, but it also uses a mask to maintain sparsity information, one bit per child.
- pointer: Store pointers instead of the whole structure to save memory and maintain sparsity.
- dynamic: Variable-length array, with a predefined maximum length. It serves the role of
std::vector
in C++ orlist
in Python, and can be used to maintain objects (e.g. particles) contained in a block.
See Advanced dense layouts for more details. ti.root
is the root node of the data structure.
-
snode.
place
(x, ...)¶ 参数: - snode – (SNode) where to place
- x – (tensor) tensor(s) to be placed
返回: (SNode) the
snode
itselfThe following code places two 0-D tensors named
x
andy
:x = ti.var(dt=ti.i32) y = ti.var(dt=ti.f32) ti.root.place(x, y) assert x.snode() == y.snode()
-
tensor.
shape
()¶ 参数: tensor – (Tensor) 返回: (tuple of integers) the shape of tensor Equivalent to
tensor.snode().shape
.For example,
ti.root.dense(ti.ijk, (3, 5, 4)).place(x) x.shape # returns (3, 5, 4)
-
tensor.
snode
()¶ 参数: tensor – (Tensor) 返回: (SNode) the structual node where tensor
is placedx = ti.var(dt=ti.i32) y = ti.var(dt=ti.f32) ti.root.place(x, y) x.snode()
-
snode.
shape
()¶ 参数: snode – (SNode) 返回: (tuple) the size of node along that axis blk1 = ti.root blk2 = blk1.dense(ti.i, 3) blk3 = blk2.dense(ti.jk, (5, 2)) blk4 = blk3.dense(ti.k, 2) blk1.shape # () blk2.shape # (3, ) blk3.shape # (3, 5, 2) blk4.shape # (3, 5, 4)
-
snode.
parent
(n = 1)¶ 参数: - snode – (SNode)
- n – (optional, scalar) the number of steps, i.e.
n=1
for parent,n=2
grandparent, etc.
返回: (SNode) the parent node of
snode
blk1 = ti.root.dense(ti.i, 8) blk2 = blk1.dense(ti.j, 4) blk3 = blk2.bitmasked(ti.k, 6) blk1.parent() # ti.root blk2.parent() # blk1 blk3.parent() # blk2 blk3.parent(1) # blk2 blk3.parent(2) # blk1 blk3.parent(3) # ti.root blk3.parent(4) # None
Node types¶
-
snode.
dense
(indices, shape)¶ 参数: - snode – (SNode) parent node where the child is derived from
- indices – (Index or Indices) indices used for this node
- shape – (scalar or tuple) shape the tensor of vectors
返回: (SNode) the derived child node
The following code places a 1-D tensor of size
3
:x = ti.var(dt=ti.i32) ti.root.dense(ti.i, 3).place(x)
The following code places a 2-D tensor of shape
(3, 4)
:x = ti.var(dt=ti.i32) ti.root.dense(ti.ij, (3, 4)).place(x)
注解
If
shape
is a scalar and there are multiple indices, thenshape
will be automatically expanded to fit the number of indices. For example,snode.dense(ti.ijk, 3)
is equivalent to
snode.dense(ti.ijk, (3, 3, 3))
-
snode.
dynamic
(index, size, chunk_size = None)¶ 参数: - snode – (SNode) parent node where the child is derived from
- index – (Index) the
dynamic
node indices - size – (scalar) the maximum size of the dynamic node
- chunk_size – (optional, scalar) the number of elements in each dynamic memory allocation chunk
返回: (SNode) the derived child node
dynamic
nodes acts likestd::vector
in C++ orlist
in Python. Taichi’s dynamic memory allocation system allocates its memory on the fly.The following places a 1-D dynamic tensor of maximum size
16
:ti.root.dynamic(ti.i, 16).place(x)
-
snode.
bitmasked
()¶
-
snode.
pointer
()¶
-
snode.
hash
()¶ TODO: add descriptions here
Working with dynamic
SNodes¶
-
ti.
length
(snode, indices)¶ 参数: - snode – (SNode, dynamic)
- indices – (scalar or tuple of scalars) the
dynamic
node indices
返回: (int32) the current size of the dynamic node
-
ti.
append
(snode, indices, val)¶ 参数: - snode – (SNode, dynamic)
- indices – (scalar or tuple of scalars) the
dynamic
node indices - val – (depends on SNode data type) value to store
返回: (int32) the size of the dynamic node, before appending
Inserts
val
into thedynamic
node with indicesindices
.
Taichi tensors like powers of two¶
Non-power-of-two tensor dimensions are promoted into powers of two and thus these tensors will occupy more virtual address space.
For example, a (dense) tensor of size (18, 65)
will be materialized as (32, 128)
.