400-123-4657
点击量:627 时间:2022-09-16
众所周知,Python的简单和易读性是靠牺牲性能为代价的
只需import 一个叫做“Taichi”的库EMC易倍,就可以把代码速度提升100倍!
不用更改任何函数体,import“taichi”库,然后再加两个装饰器:
如果N=1000万,则只要0.8s;要知道,不加它可是55s,一下子又快了70倍!
那么此时,计算所有小于1000万的素数就只耗时0.45s了,与原来的Python代码相比速度就提高了120倍!
什么?你觉得这个例子太简单了,说服力不够?我们再来看一个稍微复杂一点的。
动态规划不用多说,作为一种优化算法,通过动态存储中间计算结果来减少计算时间EMC易倍。
我们以经典教材《算法导论》中的经典动态规划案例“最长公共子序列问题(LCS)”为例。
用动态规划的思路计算LCS易倍动态,就是先求解序列a的前i个元素和序列b的前j个元素的最长公共子序列的长度,然后逐步增加i或j的值,重复过程,得到结果。
胡渊鸣电脑上的程序最快做到了0.9秒内完成,而换成用NumPy来实现,则需要476秒,差异达到了超500倍!
图灵机的发明者艾伦图灵是第一个提出模型来描述这种现象的人。
在该模型中,两种化学物质(U和V)来模拟图案的生成。这两者之间的关系类似于猎物和捕食者,它们自行移动并有交互:
为了避免U被V根除,我们在每个时间步添加一定百分比 (f) 的U并删除一定百分比 (k) 的V。
其中有四个关键参数:Du(U的扩散速度),Dv(V的扩散速度),f(feed的缩写,控制U的加入)和k(kill的缩写,控制V的去除)。
如果Taichi中实现这个方程,首先创建网格来表示域,用vec2表示每个网格中U, V的浓度值。
拉普拉斯算子数值的计算需要访问相邻网格。为了避免在同一循环中更新和读取数据,我们应该创建两个形状相同的网格W x EMC易倍H×2。
每次从一个网格访问数据时,我们将更新的数据写入另一个网格,然后切换下一个网格。那么数据结构设计就是这样:
一开始,我们将U在网格中的浓度设置为 1,并将V放置在50个随机选择的位置:
最后一步就是根据V的浓度对结果进行染色,就可以得到这样一个效果惊人的图案:
有趣的是,胡渊鸣介绍,即使V的初始浓度是随机设置的,但每次都可以得到相似的结果。
而且和只能达到30fps左右的Numba实现比起来,Taichi实现由于可以选择GPU作为后端,轻松超过了 300fps。
其实,Taichi就是一个嵌入在Python中的DSL(动态脚本语言),它通过自己的编译器将被 @ti.kernel 装饰的函数编译到各种硬件上,包括CPU和GPU,然后进行高性能计算。
正如其名,Taichi就出自太极图形胡渊鸣的团队,现在你只需要用pip install就能安装这个库,并与其他Python库进行交互,包括NumPyEMC易倍、Matplotlib和PyTorch等等。
当然,Taichi用起来和这些库以及其他加速方法有什么差别,胡渊鸣也给出了详细的优缺点对比,感兴趣的朋友可以戳下面的链接详细查看: