大家好!在做GAMES201作业的时候发现,Taichi在数组访问越界的时候并不会报错,而是直接返回0。比如说下面的例子:
x = ti.var(dt=ti.f32, shape = (3,3))
x[5,5] # Return 0.0
这样的特性在写边界条件的时候有时候挺方便的,因为不需要去特意处理越界访问,但是不知道这种做法是否推荐?越界访问返回0是Taichi语言特性故意为之,还是应该尽量避免使用?
大家好!在做GAMES201作业的时候发现,Taichi在数组访问越界的时候并不会报错,而是直接返回0。比如说下面的例子:
x = ti.var(dt=ti.f32, shape = (3,3))
x[5,5] # Return 0.0
这样的特性在写边界条件的时候有时候挺方便的,因为不需要去特意处理越界访问,但是不知道这种做法是否推荐?越界访问返回0是Taichi语言特性故意为之,还是应该尽量避免使用?
Interesting, I think this could be a per-backend feature.
@yuanming It seems our LLVM backend can automatically detect OOB and return 0.0 on that?
Not sure this works on all backends… @houkensjtu If you have OpenGL or Metal backend, could you try this out?
import taichi as ti
ti.init(arch=ti.opengl) # ti.metal if you're on Mac machine
ti.set_logging_level(ti.DEBUG)
x = ti.var(ti.f32, (10, 10))
@ti.kernel
def init():
for i, j in x:
x[i, j] = 10 * i + j
@ti.kernel
def access():
print(x[0, 11])
init()
access()
If it works, we may want to add this behavior document
BTW, FYI, if we initialize Taichi with ti.init(debug=True)
, out-of-bound will always result in a RuntimeError
.
Oh! I found that this behavior only works when the tensor size is not power-of-two:
import taichi as ti
ti.init(arch=ti.cpu)
N = 8
x = ti.var(ti.i32, N)
@ti.kernel
def test():
for i in x:
x[i] = 1000 + i
for i in ti.static(range(-N, 2 * N)):
print(i, x[i])
test()
N = 8:
-8 1000
-7 1001
-6 1002
-5 1003
-4 1004
-3 1005
-2 1006
-1 1007
0 1000
1 1001
2 1002
3 1003
4 1004
5 1005
6 1006
7 1007
8 1000
9 1001
10 1002
11 1003
12 1004
13 1005
14 1006
15 1007
N = 5:
-5 1003
-4 1004
-3 0
-2 0
-1 0
0 1000
1 1001
2 1002
3 1003
4 1004
5 0
6 0
7 0
8 1000
9 1001
N = 3:
-3 1001
-2 1002
-1 0
0 1000
1 1001
2 1002
3 0
4 1000
5 1001
I think this is related to the tensor layout: Taichi always store tensors in POT.
So when a tensor is non-POT, access OOB will get 0.
When a tensor is POT, access OOB will get x[i % N, j % N]
.
Anyway, I think we shouldn’t depend too much on this.
抱歉翻了个老贴出来。。。
刚刚重新看文档的时候发现了疑似的原因是Taichi会自动扩展张量的大小?
Taichi的张量尺寸
这如果是真的话,是不是说比如我建立一个100x100的矩阵,实际则会占领2^14 = 16384的内存空间,因为那是最接近10000的二次幂?
刚刚重新看文档的时候发现了疑似的原因是Taichi会自动扩展张量的大小?
是的,所以非2次幂的大小才会自动变成0。
这如果是真的话,是不是说比如我建立一个100x100的矩阵,实际则会占领2^14 = 16384的内存空间,因为那是最接近10000的二次幂?
不,IIRC它会变成128x128的矩阵,可能是为了要所有个索引都对齐到2才能获得最佳内存性能。
不过话又说回来。。在这个代码里
x = ti.var(dt=ti.f32, shape = (3,3))
x[5,5] # Return 0.0
x[10000,10000] # Also return 0.0!?
按照文档的说法扩展是应该扩展到4x4,但是我试了一下访问远大于这个尺寸的元素都不会报错而返回0的。不管如何,这个问题也不是很紧急。。先谢谢大佬
I believe if you use ti.init(debug=True)
then x[10000, 10000]
will give you an error