Python机器学习性能优化PyCon2

上周末在上海参加PyCon,第一次与Python爱好者们面基,顺便讲了个机器学习相关的Talk。现场反馈还不错,人工智能会场爆满,还收获不少粉丝。其中一位粉丝是人工智能的PhD,散场后交流了不少,送了我一本《深度学习》的书,才发现他是译者。其他场次比较值得一听的是英伟达讲师的分享,如果早点认识可以省去不少弯路。

大会没有直播和视频,在此分享一下我的PPT和演讲者备注。

关于我:

网易游戏大到w行python项目(听说python不适合大项目:P

Airtest开源作者star

人工智能NLP深度学习

8年Python经验,第一语言:web、自动化、游戏、ai,python可以做很多事情,每个方面的python经验其实都是可以迁移互补的。

那么我们就看看在机器学习领域,如何做python的性能优化

Q:先问一问在座多少是做AI相关,多少是想转AI方向的(应该所有人都是用python的吧

A:大部分做AI的同学都是从算法入门的,对系统和性能了解甚少。这次分享会从entrylevel开始,nodeepshit,即使没有做AI的听众也会收获一些Python和方法论经验

为什么我们这么说呢?

程序员的时间都是钱啊,特别是做优化的都是资深经验的程序员,很贵的

想象一个秒的程序,其中40秒花在运行一个函数

对于人工智能项目,更是如此,先做出效果,确定好整体的pipeline,再考虑优化

对于项目开发周期:1.先做出demo效果、验证产品2.确定整体pipeline3.再考虑性能优化

Q:了解BERT的同学有多少?没事,我尝试用一句话解释

A:BERT是google发布的预训练任务,简单来说就是用很大量的语料训练

输入一句话,转换成向量,向量就可以进行各种操作,比如取平均、取近似、做分类,取近似可以用来推荐、分类就是用来做情感分类

可以想象成一个大黑盒,黑盒里面有3亿参数,对输入的句子进行矩阵运算

bert比之前的厉害的地方是selfattention机制,句子里面的每个词和句子里每个词的关系,可以用矩阵表示

另一个特点是预训练的模型结构都一样,3亿参数,下游任务就很简单的,很简单的模型结构解决问题

完型填空就是其中一个很典型的任务,跟中国英语考试题比较类似

Q:假设我们现在上线了这样一个服务,每秒钟只能处理10个请求,大家一开始要怎么着手

A:很多人拿到这样的程序,一开始就会优化bert模型部分

但是意想不到的是热点在预处理:Tokenization

这样即使你把bert模型部分优化了很多倍,整体效率也提升不大,(因为阿木达尔定律)

只是一个引子,后面会详细讲整个一步步的优化步骤,这里先补一补基础知识

本来是想讲讲这几个资源的,但是那样太无聊,我们直接从两个问题说起:

GPU为什么快?

Python为什么慢?

Q:为什么人们说GPU比CPU快?

难道是两家技术水平差距有这么大?

NVIDIA的数据

人工智能近十年的发展得益于数据和算力的爆发式增长,而GPU的爆发得益于游戏行业的发展。。。游戏行业推动了GPU,人们却用GPU做起了人工智能

Q:为什么,难道是NVIDIA比INTEL技术好这么多吗?

不同的硬件结构,导致了不同的编程范式。GPU编程就是要扬长避短

利用好强大的多线程并行能力

cache较少,充分考虑显存读写的消耗和优化

cpu和gpu是两个硬件,完全异步

当然现在说这些有点抽象,大家有个概念,后面会有具体的例子

当各个语言的爱好者聚集在一起,说到Python总是会说Python“慢”,那么问题来了

Q:为什么人们说Python慢?

对于开发者来说,机器硬件是你的资源,操作系统是你的资源,python语言同样是你的资源。你需要先了解你的资源

为了直击python开发者的痛处,又不太像上课那么无聊,我们来看一个例子

我们来看最简单的一个例子,用flask写了server,看起来毫无问题的服务器,大家会觉得慢。

Q:那么猜一下慢在哪里?有没有同学可以说一下

Flask裸起很慢ThreadedServer,每一个请求启动一个线程。老版本更甚,是单线程server,循环处理

GIL是python语言爱好者的痛点,可以说是唯一的语言缺陷。满负荷运转也只能跑满单核,摩尔定律失效导致多核的发展,动不动就是32核

解释执行,一个1+2语句都有20多层c函数调用。导致计算密集型的函数很慢,比如json序列化。当然这不是语言缺陷,而是各种动态特性的tradeoff

web开发发展这么多年,这三个解决方案非常成熟了

直接看结果

如此一来,我们解决刚刚说的三个问题

1.多核

2.异步

3.高效序列化

我们就可以得到一个跟golang甚至c++差不多性能的webserver,轻松上10wqps

但是很多新手不知道,一跑发现比c++/go慢那么多,就到网上disspython了。

前面我们介绍了优化的哲学,优化的闭环

也初步了解了我们的资源、GPU和python语言的特性

下面我们简单说一下如何定位性能瓶颈:没有profile的优化都是耍流氓

之前都是time.time()就能确定问题,那是我们有一定的范围了,或者粗略地圈定范围。

需要正经做profile,有一个highlevel的了解

pyflame是uber开源的一个profiler,高频采样运行中的python程序,比如每秒采样次,统计正在运行的函数,统计次数就是运行时间。

欢迎使用我二次开发的版本

有了哲学、基础知识,也有了武器库(profiler)

有了之前的背景知识和方法论,我们可以正经开始优化了,第一个解决最大的热点:preprocess

preprocess做的事情很简单,我说一下大家就明白,从词典里面找到对应的词的index,把string转换成int

pybind也是pytorch和TensorFlow实现c++python接口的方式,非常简单直白。

这时候我们的热点变成了网络模型

用户请求是离散的,GPU并行度不高

生产者消费者模型

只需要几行代码进行封装,与框架完全无关,也不用改变数据处理流程

详细的请看readme

买V更好的卡,或者更多的机器

BERT既然有3e参数,我们能不能想办法减少参数

更好的实现,从这点说起

正好NVIDIA针对bert做了一套TensorRT优化,我们看看官方是如何优化实现的。

简单来说就是遵循gpu的编程范式,将数据尽可能并行,减少显存的读写次数。

而这一点可以通过自己写cuda插件来实现。我的这篇博客中有更详细的介绍

分别给个概念,说下局限性

知识蒸馏:

TeacherStudent学的更快

3亿参数始终是个问题

24层/12层蒸出6层

机器学习系统还是非常新的领域,欢迎与我多多交流

预览时标签不可点收录于合集#个上一篇下一篇

转载请注明:http://www.aierlanlan.com/tzrz/646.html