如何检查dense后pointer SNode的activity?

检查dense后pointer snode的activity时,提示SNode只有1维
[$38] S3 has 1 indices. Indexed with 2.
无法求dense[i] => pointer[i,j] 这个SNode的activity。。
可能是bug?还是我哪里的理解有问题…

pointer() SNode 和 dens().pointer().pointer()SNode都正常

ti.init(arch=ti.gpu)
pf = ti.field(ti.f64)
dpf = ti.field(ti.f64)
dppf = ti.field(ti.f64)
# pointer case
p = ti.root.pointer(ti.i, 2)
p.place(pf)
# dense => pointer case
d = ti.root.dense(ti.i, 2)
dp = d.pointer(ti.j, 2)
dp.place(dpf)
# dense => pointer => pointer case
dpp = dp.pointer(ti.j, 2)
dpp.place(dppf)

@ti.kernel
def test_pf():
    for i in pf:
        if ti.is_active(p, i):
            print(i, "active")
            
@ti.kernel
def test_dpf():
    for i, j in dpf:
        if ti.is_active(dp, [i,j]):
            print(i,j, "active")

@ti.kernel
def test_dppf():
    for i, j in dppf:
        if ti.is_active(dpp, [i,j]):
            print(i,j, "active")
test_pf()
# test_dpf() # RuntimeError
test_dppf()

ti.is_active 只能检查pointer/bitmask这类snodes,访问dpf虽然要两个index,但是只有第二层是pointer,因此test_dpf里给ti.is_active的index应该只包含第二层的

1 Like

清楚了,感谢指导:)

1 Like

好像还是不对…
如果这个pointer是多维(>=2),报错还是说SNode只有1维,无法判断这个多维pointer SNode的activity。

将上面的代码pointer维度加一维

ti.init(arch=ti.gpu)
pf = ti.field(ti.f64)
dpf = ti.field(ti.f64)
dppf = ti.field(ti.f64)
# pointer case
p = ti.root.pointer(ti.ij, (2,2))
p.place(pf)
# dense => pointer case
d = ti.root.dense(ti.i, 2)
dp = d.pointer(ti.jk, (2,2))
dp.place(dpf)
# dense => pointer => pointer case
dpp = dp.pointer(ti.jk, (2,2))
dpp.place(dppf)

@ti.kernel
def test_pf():
    for i,j in pf:
        if ti.is_active(p, [i,j]):
            print(i,j, "active")
            
@ti.kernel
def test_dpf():
    for i, j, k in dpf:
        if ti.is_active(dp, [j,k]): # no i since dense???? still error.
            print(i,j,k, "active")

@ti.kernel
def test_dppf():
    for i, j, k in dppf:
        if ti.is_active(dpp, [i,j,k]):
            print(i,j,k, "active")
test_pf()
test_dpf() # RuntimeError
test_dppf()

一个更清楚的例子

ti.init(arch=ti.gpu)
dpf = ti.field(ti.f64)
d = ti.root.dense(ti.i, 2)
dp = d.pointer(ti.jk, (2,2))
dp.place(dpf)
# inactive dpf[0,0,0]
dpf[0, 0, 1] = 1.0
dpf[0, 1, 0] = 2.0
dpf[0, 1, 1] = 3.0
# inactive dpf[1,0,0]
dpf[1, 0, 1] = 11.0
dpf[1, 1, 0] = 12.0
dpf[1, 1, 1] = 13.0

@ti.kernel
def is_active_1d(snode: ti.template(), i: ti.i32) -> ti.i32:
    return ti.is_active(snode, i)

def test_dpf():
    for i in range(2):
        if is_active_1d(dp, i):
            print(i,  "active")
        else:
            print(i,  "inactive")

test_dpf()
print(dpf)

'''
0 inactive
1 inactive
[[[ 0.  1.]
  [ 2.  3.]]

 [[ 0. 11.]
  [12. 13.]]]
'''

主要问题在于:

  1. 跟在dense后的pointer snode (dp),比如是n维,在使用ti.is_active时,提示只有一维,其实应该是(1+n)维。导致无法查询dp中元素的activity。
  2. ti.is_active似乎只检查了dp中的首个元素的activity。

一种丑陋的hack解决方式是,再加一层ugly pointer with shape (1,1)。。 :smiling_face_with_tear:

dupf = ti.field(ti.f64)

d = ti.root.dense(ti.i, 2)
du = d.pointer(ti.jk, (1,1))  # ugly pointer of shape (1,1)
dup = du.pointer(ti.jk, (2,2))
dup.place(dupf)

@ti.kernel
def test_dupf():
    for i, j, k in dupf:
        if ti.is_active(dup, [i,j,k]):
            print(i, j, k, "active")
        else:
            print(i, j, k, "inactive")

test_dupf() # working...

我觉得算是一个小bug

@identxxy 感谢报告,这的确是个 bug。我已经在 GitHub 上提了 issue 和相应的解决 PR,在下个版本中你应该就不需要 hack 了 :slight_smile:

3 Likes