代码提速100倍,怎么实现的?

news2024/11/19 13:40:06

众所周知,Python的简单和易读性是靠牺牲性能为代价的

尤其是在计算密集的情况下,比如多重for循环。不过现在,大佬胡渊鸣说了:

只需import 一个叫做“Taichi”的库,就可以把代码速度提升100倍!

不信?来看三个例子。

计算素数的个数,速度x120

第一个例子非常非常简单,求所有小于给定正整数N的素数。

标准答案如下:

 我们将上面的代码保存,运行。

当N为100万时,需要2.235s得到结果:

 现在,我们开始施魔法。

不用更改任何函数体,import“taichi”库,然后再加两个装饰器:

Bingo!同样的结果只要0.363s,快了将近6倍

如果N=1000万,则只要0.8s;要知道,不加它可是55s,一下子又快了70倍!

不止如此,我们还可以在ti.init()中加个参数变为ti.init(arch=ti.gpu) ,让taich在GPU上进行计算。

那么此时,计算所有小于1000万的素数就只耗时0.45s了,与原来的Python代码相比速度就提高了120倍!

厉不厉害?

什么?你觉得这个例子太简单了,说服力不够?我们再来看一个稍微复杂一点的。

动态规划,速度x500

动态规划不用多说,作为一种优化算法,通过动态存储中间计算结果来减少计算时间。

我们以经典教材《算法导论》中的经典动态规划案例“最长公共子序列问题(LCS)”为例。

比如对于序列a = [0, 1, 0, 2, 4, 3, 1, 2, 1]和序列b = [4, 0, 1, 4, 5, 3, 1, 2],它们的LCS就是:

LCS(a, b) = [0, 1, 4, 3, 1, 2]。

用动态规划的思路计算LCS,就是先求解序列a的前i个元素和序列b的前j个元素的最长公共子序列的长度,然后逐步增加i或j的值,重复过程,得到结果。

我们用f[i, j]来指代这个子序列的长度,即LCS((prefix(a, i), prefix(b, j)。其中prefix(a, i) 表示序列a的前i个元素,即a[0], a[1], …, a[i - 1],得到如下递归关系:

现在,我们用Taichi来加速:

结果如下:

胡渊鸣电脑上的程序最快做到了0.9秒内完成,而换成用NumPy来实现,则需要476秒,差异达到了超500倍!

最后,我们再来一个不一样的例子。

反应 - 扩散方程,效果惊人

自然界中,总有一些动物身上长着一些看起来无序但实则并非完全随机的花纹。

图灵机的发明者艾伦·图灵是第一个提出模型来描述这种现象的人。

在该模型中,两种化学物质(U和V)来模拟图案的生成。这两者之间的关系类似于猎物和捕食者,它们自行移动并有交互:

  1. 最初,U和V随机分布在一个域上;

  2. 在每个时间步,它们逐渐扩散到邻近空间;

  3. 当U和V相遇时,一部分U被V吞噬。因此,V的浓度增加;

  4. 为了避免U被V根除,我们在每个时间步添加一定百分比 (f) 的U并删除一定百分比 (k) 的V。

上面这个过程被概述为“反应-扩散方程”:

其中有四个关键参数:Du(U的扩散速度),Dv(V的扩散速度),f(feed的缩写,控制U的加入)和k(kill的缩写,控制V的去除)。

如果Taichi中实现这个方程,首先创建网格来表示域,用vec2表示每个网格中U, V的浓度值。

拉普拉斯算子数值的计算需要访问相邻网格。为了避免在同一循环中更新和读取数据,我们应该创建两个形状相同的网格W×H×2。

每次从一个网格访问数据时,我们将更新的数据写入另一个网格,然后切换下一个网格。那么数据结构设计就是这样:

一开始,我们将U在网格中的浓度设置为 1,并将V放置在50个随机选择的位置:

那么实际计算就可以用不到10行代码完成:

 

@ti.kernel
def compute(phase: int):
    for i, j in ti.ndrange(W, H):
        cen = uv[phase, i, j]
        lapl = uv[phase, i + 1, j] + uv[phase, i, j + 1] + uv[phase, i - 1, j] + uv[phase, i, j - 1] - 4.0 * cen
        du = Du * lapl[0] - cen[0] * cen[1] * cen[1] + feed * (1 - cen[0])
        dv = Dv * lapl[1] + cen[0] * cen[1] * cen[1] - (feed + kill) * cen[1]
        val = cen + 0.5 * tm.vec2(du, dv)
        uv[1 - phase, i, j] = val

在这里,我们使用整数相位(0或1)来控制我们从哪个网格读取数据。

最后一步就是根据V的浓度对结果进行染色,就可以得到这样一个效果惊人的图案

 有趣的是,胡渊鸣介绍,即使V的初始浓度是随机设置的,但每次都可以得到相似的结果。

而且和只能达到30fps左右的Numba实现比起来,Taichi实现由于可以选择GPU作为后端,轻松超过了 300fps。

pip install即可安装

看完上面三个例子,你这下相信了吧?

其实,Taichi就是一个嵌入在Python中的DSL(动态脚本语言),它通过自己的编译器将被 @ti.kernel 装饰的函数编译到各种硬件上,包括CPU和GPU,然后进行高性能计算。

有了它,你无需再羡慕C++/CUDA的性能。

正如其名,Taichi就出自太极图形胡渊鸣的团队,现在你只需要用pip install就能安装这个库,并与其他Python库进行交互,包括NumPy、Matplotlib和PyTorch等等。

当然,Taichi用起来和这些库以及其他加速方法有什么差别,胡渊鸣也给出了详细的优缺点。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/69821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VTK - vtkPolyData数据的Remesh

欢迎加入我的VTK社区 雪易VTK社区-CSDN社区云 前言:在研究3-matic软件中smooth Edge和Local Smoothing功能时,先对数据的网格进行了重新的划分,即3-matic软件中的Remesh功能。本博文主要针对Remesh进行展开。 目录 网格质量 vtkMeshQuali…

【JavaScript】ESLint 深入浅出

▒ 目录 ▒🛫 导读需求开发环境1️⃣ 初体验安装lint配置.eslintrc.js忽略文件package.json中添加eslint脚本2️⃣ vscode中使用插件安装作用3️⃣ 规避报错问题行添加注释问题文件开头添加注释修改配置文件.eslintrc.js4️⃣ 常见错误汇总Cannot read property nam…

站在巨人的肩膀上,用Node+ChatGPT模块实现一个接口

目录 前言 准备工作 起步 写在最后 前言 蹭一下最近比较火的人工智能ChatGPT的热度,最近看到许多小伙伴都在调戏ChatGPT,看到这我就坐不住了,这种事怎么能少了我,于是闲(划)暇(水&#xff0…

什么事Jupyter Notebook?

Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。 简而言之,Jupyter Notebook是以网页的形式打开,可以在网页页面中直接编写代码和运行代码,代码的运行结果也…

【javascript】 初见浏览器端日志系统 log4js、bunyan

▒ 目录 ▒🛫 导读需求开发环境1️⃣ log4js配置实现2️⃣ bunyan自定义MyRawStream实现🛬 文章小结📖 参考资料🛫 导读 需求 用习惯了python、java的日志系统,现在使用console.log等览器端js接口打印日志&#xff0c…

m基于FPGA的多级抽取滤波器组verilog设计,包括CIC滤波,HB半带滤波以及DA分布式FIR滤波

目录 1.算法描述 2.仿真效果预览 3.verilog核心程序 4.完整FPGA 1.算法描述 数字下变频中的低通滤波器是由多级抽取滤波器组实现的。信号的同相分量和正交分量再分别经由积分梳状滤波器(CIC)、半带滤波器(HB)和有限长单位脉冲响应(FIR)滤波器构成的多级抽取滤波器组进行滤波…

vcenter开机报错activating swap-devices in /etc/fstab

问题:昨天IDC机房一台存储断电了,恰巧vcenter在这台存储上,重启存储后再重启vcenter报了以下错误: 参考文档: https://www.virtualizestuff.com/2015/10/29/vcsa_fstab_failed/ https://kb.vmware.com/s/article/2069…

政企数智办公潮水里的融云「答卷」

在这张集合了党政机关、金融保险、交通、能源电力等中大型组织复杂办公需求的高难度答卷上,融云在扎实耐打的通信底层之上,保持灵活的身段和强大的进化能力,稳定而轻盈,在不断变化的环境中正在成为确定性本身。 作者|皮爷 出品…

手把手教你打造一款个人专属Android桌面

实现方式两种 1.从头到尾写一个apk然后把系统的属性加上去,然后启动的时候默认就指定到这个apk的包名,他就启动, 2.我们基于Androidlauncher3的源码去做一个定制化的修改 分析一下这两种的区别, 自定义,要有丰富的…

使用SuperMap iDesktopX如何去掉“耗子尾巴”

在项目中,通过会遇到一些错误的矢量数据,比如“耗子尾巴”。什么是“耗子尾巴呢”,我们所说的“耗子尾巴图斑”,是不规则图斑的一种形态。规则的图斑,应该形态接近圆、矩形、菱形或凸多边形的图斑。自然界中多数图斑应…

[附源码]计算机毕业设计JAVA政府项目管理平台

[附源码]计算机毕业设计JAVA政府项目管理平台 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybati…

ASEMI整流桥MB10F、MB6S、ABS10参数对比

编辑-Z 封装和参数是工程师在选型整流桥时的两大重要依据,下面我们就把比较常见的ASEMI整流桥MB10F、MB6S、ABS10参数做个对比,方便大家选型。 整流桥MB10F参数: 型号:MB10F 封装:MBF-4 最大重复峰值反向电压&…

Redis - Linux下载与安装

1.通过apt方式安装Redis 在终端中输入,如下命令进行安装: # 更新软件源 sudo apt update # 安装redis-server sudo apt install redis-serverredis服务安装完成后,服务将自动启动。通过如下命令查看服务进程是否启动: ps aux |…

快速上手Django(八) -Django之 统一异常、Response处理

文章目录快速上手Django(八) -Django之 统一异常、Response处理一、统一Response处理二、统一异常处理1. 需求背景2. Django、drf统一异常处理3. Django、drf异常处理基础4. 纯django场景下5. 【重要】使用drf场景下,实现思路编写自定义异常处理方法在settings/dev.…

高端前端彻底搞定this指向(详解)

这篇文章只告诉你三件事情,this,this,还TM的是this。 1,this在javascript中是可有可无的 大家在学习javascript的时候,肯定或多或少看到过了很多代码。其中肯定会发现this的身影。我们知道他是代表的指向,可是让人迷惑的是this的…

Scheduled定时任务异步执行

1.使用配置 我在使用SpringBoot配置定时任务的过程中,使用Scheduled配置了多个定时任务,但是在项目启动的时候每次只会启动一个定时任务,只好搜索一波,直到看到了 ThreadPoolTaskScheduler的源码,才发现默认开启的线程数是 1 Configuration public class ScheduledPoolConfi…

如何用代码实现决策树来决策要不要相亲?

前言 上一篇我们了解了什么是决策树,知道了决策树构建的过程,同时聊了构建决策树的两种算法,那么我们今天来看下如何使用代码实现决策树的构建。 数据分析整体流程 数据分析一般是以下的分析流程 1、加载数据集 首先我们构建数据,提供训…

windows10配置openvino

一、前言 gpu的常用部署我们是选择trt,那么cpu的部署呢?当然是英特尔的ov 这里要注意:我们一般是现在一台机器上利用exe(后续会说)安装完ov,那么以后在配好第一台软件配置后,以后部署到其他机器上只需要直接把dll和lib直接复制到另一台就可以运行了! 也就是说,只有…

Matplotlib学习笔记(第二章 2.11使用指南 一些简单的例子)

第二章 学习指南 本页包含更多使用Matplotlib的深入指南。它分为初级、中级和高级部分,以及涵盖特定主题的部分。 有关较短的示例,请参阅我们的示例页面。您还可以在我们的用户指南中找到外部资源和FAQ。 2.1介绍 这些教程涵盖了使用Matplotlib创建可…

P4设计实现链路监控

实验要求 在本次实验中,目的是编写一个P4程序,使主机能够监控网络中所有链路的使用情况本练习基于基本的IPv4转发练习,因此请确保在尝试此练习之前完成此练习(basic.p4)具体来说,我们将修改基本P4程序以处…