Concisely describe the proposed feature
I'd like to dynamically create new ti.field after materialization.
Currently our design makes appending new field into ti.root extremely hard.
For example, OpenGL backend will sort fields from smaller to larger, within ti.root.
So, my suggestion is to:
Describe the solution you'd like (if any)
We may have multiple root, each ti.field will be placed into the current active root.
And ti.root will be a proxy for ti.get_active_root(). Or even crazy, deprecate ti.root, always create a new root instead:
root = ti.create_root()
x = root.field(float, shape=233)
y = ti.field(float)
root.dense(ti.i, 233).place(y)
Then, materialize() is a per-root method. One of the root is materialized, doesn't mean all other roots are materialized.
This also allows Taichi THREE to have the free to separate its rendering field layouts from computation field layouts. Just like TensorFlow supports multiple sessions, despite we usually use the default session.
Additional comments
Related issue = https://forum.taichi.graphics/t/diy-taichi/1129/2
Dynamically creating ti.field is a nice idea and is certainly doable! However, I don't think we should use multiple root nodes - instead, we should using a single root node that allows adding/deleting children.
This will be a large-scale change. Before implementation, please come up with a design doc and make sure everyone is on the same page.
Thanks!
adding/deleting children.
So, deleting children will cause all kernels using that result in segfault or assertion failure?
So added children must be append to the tail of current root, otherwise the SNodes before it will change their address, causing already-compiled-kernels result in segfault?
No need to be aggressive here. Please modify the comment above. Otherwise, I will not continue the discussion. Thanks.
Sorry, I didn't mean to be aggressive at all. I'll try to avoid So in future talk so that people won't feel being aggressived.
Let me demonstrate my concern by an example:
x = ti.field(float, 233)
y = ti.field(float, 233)
@ti.kernel
def my_copy():
for i in x:
x[i] = y[i]
my_copy()
x.delete_from_root()
my_copy() # what will happen?
z = ti.field(float, 230) # create new field after materialization
# will z occupy the same starting memory address as `x`?
# if not, a serious memory leakage will occur.
# if so, then calling an already-bound-to-x kernel can cause UB:
my_copy() # what will happen? copy into z instead?
# or what if:
z = ti.field(float, 240) # create new field after materialization
# will z be placed after y in memory address?
As you can see, the size of z is determining the best memory location of it, otherwise we will suffer memory leakage on the long run. That means we might need a memory manager within root.
Though I was experienced with writing a mm when developing my hobby OS, implementing a high-efficiency mm is extremely hard and increases the maintain cost. We'd better make use of the system's own mm, i.e. malloc instead, which is maintained by more experienced developers.
Not sure what's happening here... but I hope everyone in the community communicate in a healthy way.
如果大家对英语的语气拿捏还不是很确定的话也可以用中文?我知道用英语的初衷是让国外的开发者也可以读懂,但是如果使用英语对社区活动有现实的损害的话,还是可以考虑加一些中文的把。。感谢两位大佬对于Taichi一直以来的投入和劳动,谢谢!
Most helpful comment
Not sure what's happening here... but I hope everyone in the community communicate in a healthy way.
如果大家对英语的语气拿捏还不是很确定的话也可以用中文?我知道用英语的初衷是让国外的开发者也可以读懂,但是如果使用英语对社区活动有现实的损害的话,还是可以考虑加一些中文的把。。感谢两位大佬对于Taichi一直以来的投入和劳动,谢谢!