结构节点 (SNodes)
在编写计算部分的代码之后,用户需要设定内部数据结构的层次。包括微观和宏观两部分,宏观上设定层级数据结构组件之间的嵌套关系以及表示稀疏性的方式;微观上,描述数据如何分组(例如,SOA 或 AOS)。Taichi 提供了 结构节点 (SNodes) 以满足不同层级数据结构构建时的需求。其结构和语义具体如下所示:
- 稠密集合(dense):固定长度的连续数组。
- 位掩码集合(bitmasked):类似于稠密集合,但实现了通过掩码保持数据的稀疏信息。比如为稠密集合的元素分配掩码来记录稀疏信息。
- 指针集合(pointer):存储指针而不是整个结构,以节省内存和保持稀疏性。
- 动态集合(dynamic):可变长度数组,具有预定义的最大长度。它有着像 C++ 中的
std::vector
或者是 Python 中的list
这样的功能,可以用来维护包含在一个块(block)中的对象(例如粒子)。
你可以在 Advanced dense layouts 章节中了解更多详细信息。 ti.root
是层级数据结构的根结点.
snode.``place
(x, …)
参数: |
|
---|---|
返回: | (结构节点) |
以下示例代码放置了 x
和 y
两个零维张量:
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.snode().shape
。
例如,
ti.root.dense(ti.ijk, (3, 5, 4)).place(x)
x.shape # 返回 (3, 5, 4)
tensor.``snode
()
参数: | tensor – (张量) |
---|---|
返回: | (结构节点) tensor 所在的结构节点 |
x = ti.var(dt=ti.i32)
y = ti.var(dt=ti.f32)
ti.root.place(x, y)
x.snode()
snode.``shape
()
参数: | snode – (结构节点) |
---|---|
返回: | (元组)张量在指定轴上的尺寸 |
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)
参数: |
|
---|---|
返回: | (结构节点) |
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
不同类型的节点
snode.``dense
(indices, shape)
参数: |
|
---|---|
返回: | (结构节点)派生出来的子节点 |
以下示例代码放置了尺寸为 3
的一维张量:
x = ti.var(dt=ti.i32)
ti.root.dense(ti.i, 3).place(x)
以下示例代码放置了尺寸为 (3,4)
的二维张量:
x = ti.var(dt=ti.i32)
ti.root.dense(ti.ij, (3, 4)).place(x)
注解
如果给定的 shape
是一个标量,却又对应了多个索引,那么 shape
将自动扩充直至和索引数量相等。例如,
snode.dense(ti.ijk, 3)
相当于
snode.dense(ti.ijk, (3, 3, 3))
snode.``dynamic
(index, size, chunk_size = None)
参数: |
|
---|---|
返回: | (结构节点)派生出来的子节点 |
动态集合
节点就像 C++ 中的 std::vector
或者是 Python 中的 list
。Taichi 具有的动态内存分配系统可以实现自由的分配内存。
以下示例代码放置了最大尺寸为 16
的一维动态张量:
ti.root.dynamic(ti.i, 16).place(x)
snode.``bitmasked
()
snode.``pointer
()
snode.``hash
()
TODO: add descriptions here
动态集合节点的使用
ti.``length
(snode, indices)
参数: |
|
---|---|
返回: | (int32)当前动态集合节点的尺寸 |
ti.``append
(snode, indices, val)
参数: |
|
---|---|
返回: | (int32) 进行附加操作之前的动态节点尺寸 |
使用上述函数,就能实现通过 索引(indices)
将 常量(val)
插入到 动态集合
节点中。
Taichi 的张量尺寸
对于张量,非整二次幂的那些维度会被扩充为整二次幂,因而会占据更多虚拟地址空间。例如,一个 (18, 65)
的稠密张量在实际存储时相当于一个 (32, 128)
大小的张量。
索引
ti.``i
ti.``j
ti.``k
ti.``ij
ti.``ji
ti.``jk
ti.``kj
ti.``ik
ti.``ki
ti.``ijk
ti.``ijkl
ti.``indices
(a, b, …)
(TODO)