Struct-for和range-for的区别

在官方文档里说到,struct-for和range-for在outermost scope都会被自动并行化,这两者在并行化上面有什么区别吗?

另外,文档里提到

Struct-for is the key to Sparse computation (WIP) in Taichi, as it will only loop over active elements in a sparse field. In dense fields, all elements are active.

这里说的key是会自动遍历active的元素,这个active与否具体是如何判别的呢?在构建稀疏矩阵时有什么需要注意的?

谢谢!

当用于稠密矩阵时,理论上是没有任何区别的。
任何曾经被写入过的元素都会变成active元素。
所有元素初始化默认为inactive。
可以通过ti.deactivate手动设为inactive。
可以通过ti.activate手动设为active。
注意:
首次初始化时要用range-for,不然因为所有元素一开始都inactive,struct-for不会遍历任何元素。
from_numpy只会初始化active的元素。to_numpy只会导出active的元素,inactive部分导出为0。
有时稀疏矩阵会反而很慢。

1 个赞

我去尝试了一下如下简单的脚本,好像struct-for也可以遍历所有元素的样子:

import taichi as ti

ti.init()
A = ti.field(dtype=ti.f32, shape=5)

@ti.func
def init():
    # 用struct-for尝试初始化
    for i in A:
        A[i] = 1.0

@ti.kernel
def main():
    init()
    for i in A:
        print(A[i])

main()

结果是这样的,所有元素都被成功赋值了。

[Taichi] mode=release
[Taichi] preparing sandbox at /tmp/taichi-kr5kb22o
[Taichi] version 0.6.27, llvm 10.0.0, commit a34a6128, linux, python 3.7.3
[Taichi] Starting on arch=x64
[Taichi] materializing...
1.000000
1.000000
1.000000
1.000000
1.000000

我也试了一下用range-for去初始化部分元素,留下一部分不碰,然后用struct-for遍历,好像所有元素都被访问了?

这是因为ti.field在指定了shape时会默认分配一个稠密矩阵
要让一个矩阵变成稀疏的,就需要先不指定shape,然后用ti.root语法放置这些矩阵:

  1. 使用位掩码的稀疏格式:
A = ti.field(dtype=ti.f32)
ti.root.bitmasked(ti.i, 5).place(A)
  1. 使用指针的稀疏格式:
A = ti.field(dtype=ti.f32)
ti.root.pointer(ti.i, 5).place(A)
  1. 使用动态长度数组的稀疏格式:
A = ti.field(dtype=ti.f32)
ti.root.dynamic(ti.i, 5).place(A)
  1. 使用稠密格式,和指定shape时等价:
A = ti.field(dtype=ti.f32)
ti.root.dense(ti.i, 5).place(A)
1 个赞

昨天跑去看了下GAMES201的第九讲才发现这些内容都多少有所涉及了。。不过现在对于root下面一层的各种格式还不是很理解。如果有什么比较好的材料或者代码演示请推荐!