Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data. It means that a program can be designed to read, generate, analyze or transform other programs, and even modify itself while running.
大体意思就是说,我们可以编写一部分代码(元编程),让这部分代码去产生那部分可以真正运行的代码,然后再让这部分运行的代码,去完成相应的计算,得到结果。
比如说:(仅仅个人理解)
下面这个图,是我们平常程序员所编写的程序,一般来说,我们要解决几个不同的问题,都要去相对应的去编写代码,也就是有几个问题,我们就会编写出几个不同的程序。
而元编程是,面对几个不同的问题,我们先大体设计出代码,也就是绘制出一张图纸,这样再面对不同的问题的时候,就可以只更改图纸上的某个部分,从而解决问题,不再需要去重新编写代码。
应用一(模板复用)Unify the development of dimensionality-dependent code, such as 2D/3D physical simulations
ti.template()这个就是taichi的元编程的函数,它具体的用处可以使用下面的例子来进行说明:
@ti.kernel
def copy(src: ti.template(), dst: ti.template(), size: ti.i32):
for i in range(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)
copy(a, b, 4)
copy(c, d, 12)
因为我们知道,taichi是一个强类型的语言,所以,在传入参数时必须指定参数的类型,但是,这个函数,我们要实现拷贝,但是,参数类型那么多,难道我们要写所有类型的拷贝函数嘛?其实是不用的,ti.template()这个代码就解决了这个问题,它将会在代码在执行时,自动判别出类型,并将程序代码放在相应的位置上,这样,我们就不需要写出所有类型的copy函数啦,直接使用带有ti.template()的copy函数就可以了。
注意:
(1)ti.template()函数,仅仅可以识别taichi中定义的参数类型,传入其它类型会进行报错
例如:
(2)ti.template()函数中,也就是taichi scope中无法对python scope中的数据进行修改
例如:
但是,直接对全局变量,也就是带有field的变量进行修改,是可以的。
(3)ti.template()函数,taichi scope中的数据,可以被taichi scope中 *** 作修改
我现在感觉,kernel也好,func也好,都是类似于C++环境,也就是说,这个ti.template()函数是传入的类似于c++中的引用(&),从而可以在taichi scope中进行修改。但是,python scope(也就是python环境)中的数据无法被taichi scope修改。
明白上述规则之后,就可以写出适应于taichi所有数据类型进行copy的函数了。
@ti.kernel
def copy(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)
但是,这样仅仅支持一维的field,如果我们想要copy多维的field呢,难不成像这样一样?
import taichi as ti
ti.init(arch=ti.cpu)
@ti.kernel
def copy_1D(x: ti.template(), y: ti.template()):
for i in x:
y[i] = x[i]
@ti.kernel
def copy_2d(x: ti.template(), y: ti.template()):
for i, j in x:
y[i, j] = x[i, j]
@ti.kernel
def copy_3d(x: ti.template(), y: ti.template()):
for i, j, k in x:
y[i, j, k] = x[i, j, k]
这样就有了下面的函数:ti.grouped()
ti.grouped()继续上面的问题,当我们使用了ti.grouped()函数之后,就可以写成:
@ti.kernel
def copy(x: ti.template(), y: ti.template()):
for I in ti.grouped(y):
# I is a vector with dimensionality same to y
# If y is 0D, then I = ti.Vector([]), which is equivalent to `None` used in x[I]
# 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]
是不是就很方便了,遍历i,j,k····都需要I就可以了,这样就可以遍历所有的field中的元素了。
应用二:加快taichi代码 ti.static()(1)强行将循环展开
也就是在kernel中的for循环将不再并行化,而是直接展开。
例如这两个程序:
from numpy import intp
import taichi as ti
ti.init(arch=ti.gpu)
@ti.kernel # 并行
def foo(x: ti.template()):
for i in range(x):
print(i)
x = int(input("Enter x: "))
foo(x)
from numpy import intp
import taichi as ti
ti.init(arch=ti.gpu)
@ti.kernel
def foo(x: ti.template()):
for i in ti.static(range(x)): #强行将循环展开
print(i)
x = int(input("Enter x: "))
foo(x)
面向对象编程
面向对象:
就是python中定义类和对象等相关的方法
taichi当中的类:@ti.data_orientedtaichi当中的类就是利用python中的类的定义方法以及使用方法,只不过需要在类前面加上 @ti.data_oriented
比如:
@ti.data_oriented
class TaichiWheel:
def __init__(self, radius, width, rolling_fric):
self.radius = radius
self.width = width
self.rolling_fric = rolling_fric
self.pos = ti.Vector.field(3, ti.f32, shape=4)
@ti.kernel
def Roll(self):
...
@ti.func
def foo(self):
...
那么加上这个@ti.data_oriented之后,就可以定义一个taichi的类了,具体的用处是:
- 可以在taichi的类中定义taichi语言所支持的数据类型
- 也可以在taichi类中利用@kernel定义并行计算的函数来提高性能了
比如:
@ti.data_oriented
class CelestialObject:
def __init__(self):
self.pos = ti.Vector(2, ti.f32, shape = N)
self.vel = ti.Vector(2, ti.f32, shape = N)
self.force = ti.Vector(2, ti.f32, shape = N)
@ti.data_oriented
class CelestialObject:
...
@ti.kernel
def update(self, h: ti.f32):
for i in self.vel:
self.vel[i] += h * self.force[i] / self.Mass()
self.pos[i] += h * self.vel[i]
当然,在taichi中也支持了三大件:封装、继承、多态
封装封装:就是把类的成员变量和成员函数都封装起来,使得外部无法访问到类的成员变量和成员函数
继承继承:就是把一个类的成员变量和成员函数继承到另一个类中,使得另一个类可以访问到父类的成员变量和成员函数
多态就是虽然外部调用的函数名相同,但是属于不同类的函数,其实现的方式可能是不同
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)