稀疏数据,显式停用单元格后,仍存在赋值

稀疏数据,显式停用单元格后,仍存在赋值,测试代码如下:

import taichi as ti
ti.init(arch=ti.cuda,device_memory_GB=4)
A = ti.field(dtype=ti.i32)
B = ti.field(dtype=ti.i32)
block = ti.root.pointer(ti.ij,(2,2))
block1 = block.pointer(ti.ij,(2,2))
block2 = block.bitmasked(ti.ij,(2,2))
block1.place(A)
block2.place(B)
       
@ti.kernel
def test():
    for i,j in ti.ndrange(4,4):
        A[i,j] = 5
        B[i,j] = 6
    ti.deactivate(block1,[2,2])
    ti.deactivate(block2,[2,2])
    print( A[2,2] , ti.is_active(block1,[2,2]) ) # 0 , 0
    print( B[2,2] , ti.is_active(block2,[2,2]) ) # 6 , 0 已停用 但赋值存在
    
    A[2,2] = 5
    B[2,2] = 6
    ti.deactivate(block1,[2,2])
    ti.deactivate(block2,[2,2])
    print( A[2,2] , ti.is_active(block1,[2,2]) ) # 5, 0  已停用 但赋值存在
    print( B[2,2] , ti.is_active(block2,[2,2]) ) # 6 , 0 已停用 但赋值存在
test()

block1.deactivate_all()
block2.deactivate_all()
print( A[2,2]) # 0 
print( B[2,2]) # 6 已停用 但赋值存在

image

当Snode 为 pointer时:
(1)ti.deactivate() 能停用在循环中进行赋值的单元格,并消除赋值,但若像上述代码中直接令A[2,2] = 5后,再对该单元格进行显示停用,虽ti.is_active()检测为未激活,但其赋值并未被消除,输出显示值仍为5。
(2)Snode.deactivate()可以停用,并消除赋值,正常。

当Snode 为 bitmasked时:
(1)无论用循环对单元格赋值还是直接令某一单元格如上B[2,2]=6,ti.deactivate()显示停用单元格后,虽显示未激活,但单元格赋值仍为6。
(2)Snode.deactivate_all() 停用所有bitmasked 后(如上代码中block2.deactivate_all() ),单元B[2,2]赋值仍为6,并未被消除至0。
以上是我遇到的几个问题,求大佬解答,谢谢!

Hi ZhangJing,
非常感谢你提的问题!我大致看了一下,目前来看Pointer SNode和Bitmasked SNode的运行时垃圾回收策略不太一致,可能是Bitmasked SNode GC策略有问题导致的。

我会继续往里研究一下,如果确实有bug的话会提Issue + 修复,再次感谢帮助我们发现问题!

Hi ZhangJing,
我看了一下bitmasked底层实现,内存的分配、回收会发生在pointer上,而bitmasked不承担内存管理的作用。如果想要回收内存,可以在bitmasked上层的pointer上调用deactivate,比如将你的代码修改为:

B = ti.field(dtype=ti.i32)
block = ti.root.pointer(ti.ij,(2,2))
block2 = block.bitmasked(ti.ij,(2,2))
block2.place(B)

@ti.kernel
def test():
    for i,j in ti.ndrange(4,4):
        B[i,j] = 6
    
    # 想要回收bitmasked(block2)的内存,
    # 需要调用其上层pointer(block)的deactivate
    ti.deactivate(block,[1,1])

1 个赞

万分感谢解答困惑,谢谢!