defcopy_4(src, dst): for i inrange(4): dst[i] = src[i]
a = ti.field(ti.f32, 4) b = ti.field(ti.f32, 4)
copy_4(a, b)
现在有两个类型为 Taichi field 的四维数组,我想做一次拷贝。如果在 Python- scope 直接让 b = a 的话会指向同一块内存,上面是一个比较天真的拷贝实现。
1 2 3 4 5 6 7 8 9 10 11
defcopy(src, ddst, size): for i inrange(size): dst[i] = src[i] a = ti.field(ti.f32, 4) b = ti.field(ti.f32, 4) c = ti.field(ti.f32, 12) d = ti.filed(ti.f32, 12)
copy(a, b, 4) copy(c, d, 12)
有人会说之前的代码复用性差,我们可以把长度也作为一个参数传进来完成拷贝。
1 2 3 4 5 6 7 8 9 10 11 12
@ti.kernel defcopy(src: ti.template(), dst: ti.template(), size: ti.i32): for i inrange(size): dst[i] = src[i] a = ti.field(ti.f32, 4) b = ti.field(ti.f32, 4) c = ti.field(ti.f32, 12) d = ti.field(ti.f32, 12)
@ti.func defmy_func(x: ti.template()): x += 1# This line will change the original value of x @ti.kernel defmy_kernel(): x = 24 my_func(x) print(x) # 25
@ti.kernel defcopy(src: ti.template(), dst: ti.template()): for i in src: dst[i] = src[i]
a = ti.field(ti.f32, 4) b = ti.field(ti.f32, 4) c = ti.field(ti.f32, 12) d = ti.field(ti.f32, 12)
copy(a, b) copy(c, d)
在熟悉 ti.template() 后我们可以把参数 size 甩掉了,因为传进两个 field 就直接可以用 Taichi struct-for 的形式进行循环调用,直接进行拷贝操作。
同理拷贝 ti.Vector.field 等等也可行,只要 shape 长得一样就ok。
如果 shape 不一样,在 Taichi struct-for 需要使用 for i, j in src: 这种形式专门处理 c 到 d 的拷贝,这种情况下也许需要写好几个函数。
Dimension independent programming
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@ti.kernel defcopy_1D(x: ti.template(), y: ti.template()): for i in x: y[i] = x[i] @ti.kernel defcopy_2D(x: ti.template(), y: ti.template()): for i, j in x: y[i, j] = x[i, j] @ti.kernel defcopy_3D(x: ti.template(), y: ti.template()): for i, j, k in x: y[i, j, k] = x[i, j, k]
@ti.kernel defcopy(x: ti.template(), y: ti.template()): for I in ti.grouped(y): # if y is 0D, then I = ti.Vector([]) # if y is 1D, then I = ti.vector([i]) # if y is 2D, then I = ti.Vector([i, j]) # if y is 3D, then I = ti.Vector([i, j, k]) x[I] = y[I]
可不可以再给力一些?当然可以,我们可以把这些函数 group 成同一个函数,I 作为 ti.grouped() 返回类型相同的 field。
Metadata
1 2 3 4 5 6 7 8 9 10 11 12
import taichi as ti ti.init(arch = ti.cpu, debug = True)
@ti.kernel defcopy(src: ti.template(), dst: ti.template()): assert src.shape == dst.shape for i in dst: dst[i] = src[i] a = ti.field(ti.f32, 4) b = ti.field(ti.f32, 100) copy(a, b)
@ti.kernel deffoo(): for i in ti.static(range(4)): print(i) # is equivalent to: @ti.kernel deffoo(): print(0) print(1) print(2) print(3)
它也能帮助我们做一些循环展开,上面的 for 比如不需要并行,我们可以使用 ti.static() 手动拆开。
1 2 3 4 5 6 7 8
# Here we declare a field contains 8 vectors. Each vector contains 3 elements. x = ti.Vector.field(3, ti.f32, shape=(8)) @ti.kernel defreset(): for i in x: for j in ti.static(range(x.n)): # The inner loop must be unrolled since j is an index for accessing a vector x[i][j] = 0
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14
@ti.kernel defcomputeForce(self, stars: ti.template()): self.clearForce() for i inrange(self.n): p = self.pos[i]
for j inrange(self.n): if i != j: diff = self.pos[j] - p r = diff.norm(1e-2) self.force[i] += G * self.Mass() * self.Mass() * diff / r**3 for j inrange(stars.Number()): diff = stars.Pos()[j] - p r = diff.norm(1e-2) self.force[i] += G * self.Mass() * stars.Mass() * diff / r**3
面向对象编程
If you want to build a car… (POP)
Object-oriented programming (OOP)
Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”.