如何重定向kernel (cuda) 输出print函数?

如题。kernel (cuda) 中的print函数输出可以重定向到文件或者变量吗?

我尝试过更改python的sys.stdout和使用库contextlib.redirect_stdout,都无法重定向kernel的输出,文件和变量都不行。。请问如何重定向kernel输出呢?

More generally, how to serialize a field stored in a sparse SNode?
怎么把储存在稀疏数据结构上的field序列化,感觉这是一个比较重要的功能…

求求巨佬解释一下相关问题

Taichi kernel 里面的 print 调用的不是 Python 的 print 函数,所以你那样修改是不起作用的。

请问有什么好的办法重定向kernel的输出呢?

可以试着在终端里做标准输出重定向,例如 python3 test.py > test.out
我理解你说的序列化是转成方便的格式存储到硬盘?可以试试把下标与对应值存到 numpy array 中之后序列化。

1 个赞

感谢指导,终端的重定向是work的,但是就不是很方便。。

将下标存在numpy array里其实是我最初采用的办法,但是问题是GPU并行时,其实每个thread不知道自己该储存在numpy array里的第几个,因为它不知道已经存了几个。。这里有一个implicit serialization(串行)。

我本来是想利用print时的隐式串行来完成稀疏field的序列化。但就是重定向不大方便。。

一个简单(但不一定快)的方法是存一个当前长度,每次存储时用 atomic_add 获取当前 thread 应该存放的下标。

请问 += 操作就是 atomic_add 吗?我理解是不行的。

如下的操作是中, idx[None] 只会有两个值,在kernel前是0,在kernel后是N,不会有中间的值。

idx = ti.field(ti.i32, shape=())

@ti.kernel
def f():
    for i, j, k in field:
        print(idx[None])
        idx[None] += 1 # or ti.atomic_add(idx[None], 1).  Both not working.

我理解你说的办法实际上是完全串行的思路,实际上相当于用CPU去过一遍所有的pointer,手动检查activity

ti.loop_config(serialization=True)
for i in range():
    for j in range():
         for k in range():
             if(ti.is_active(field, [i,j,k])): idx += 1

但这种方法在数据结构非常稀疏时,尤其是是N^3的情况,显然是非常慢的。。

idx = ti.field(ti.i32, shape=())

@ti.kernel
def f():
    for i, j, k in field:
        print(idx[None])
        n = ti.atomic_add(idx[None], 1)
		ext_idx[n] = [i, j, k]
		ext_val[n] = field[i, j, k]

这种感觉

:smiling_face_with_tear: