python sum函数numpy_如何用numba加速python?

6d0c3611f87672547158c9f5a37c398e.png

我把写好的markdown导入进来,但是没想到知乎的排版如此感人。如果对知乎排版不满想要看高清清爽版,请移步微信公众号原文 如何用numba加速python?同时欢迎关注

5c2e40bcb1f76c842903581740d34db2.png


前言

说道现在最流行的语言,就不得不提python。可是python虽然容易上手,但速度却有点感人。如何用简单的方法让python加速到近乎可以媲美C的速度呢?今天来就来谈谈numba这个宝贝。对你没看错,不是numpy,就是numba。

目录

用函数编程

Numba的优势

如何使用numba

​ 只用1行代码即可加速,对loop有奇效

​ 兼容常用的科学计算包,可以创建ufunc

​ 会自动调整精度,保证准确性

拓展

​ 更多numba的加速选项

​ Numba的精度问题

附录


用函数编程

在面对一个计算project的时候,我们最容易想到的就是直接码代码,最后写出一个超长的程序。这样一来,一旦出错往往就需要花很多时间定位问题。

有一个简单的办法解决这个问题,就是定义各种各样的函数,把任务分解成很多小部分。因为每个函数都不是特别复杂,并且在写好的时候就可以随时检查,因此简洁的主程序一旦出问题就很容易定位并解决。面向对象编程的思想就是基于函数。

写好函数之后,还可以使用装饰器(decorator)让它变得强大。装饰器本身是一个函数,不过是函数的函数,目的是增加函数的功能。比如首先定义一个输出当前时间的函数,再定义一个规定时间格式的函数,把后一个函数作用在前一个函数上,就是一个装饰器,作用是用特定格式输出当前时间。

Numba的优势

1.简单,往往只要1行代码就有惊喜;

2.对循环(loop)有奇效,而往往在科学计算中限制python速度的就是loop;

3.兼容常用的科学计算包,如numpy、cmath等;

4.可以创建ufunc;

5.会自动调整精度,保证准确性。

如何使用numba

针对上面提到的numba的优势,我来进行逐一介绍。首先导入numba

import numba as nb

只用1行代码即可加速,对loop有奇效

因为numba内置的函数本身是个装饰器,所以只要在自己定义好的函数前面加个@nb.jit()就行,简单上手。下面以一个求和函数为例

# 用numba加速的求和函数
@nb.jit()
def nb_sum(a):Sum = 0for i in range(len(a)):Sum += a[i]return Sum# 没用numba加速的求和函数
def py_sum(a):Sum = 0for i in range(len(a)):Sum += a[i]return Sum

来测试一下速度

import numpy as np
a = np.linspace(0,100,100) # 创建一个长度为100的数组%timeit np.sum(a) # numpy自带的求和函数
%timeit sum(a) # python自带的求和函数
%timeit nb_sum(a) # numba加速的求和函数
%timeit py_sum(a) # 没加速的求和函数

结果如下

# np.sum(a)
7.1 µs ± 537 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# sum(a)
27.7 µs ± 2.64 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# nb_sum(a)
1.05 µs ± 27.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# py_sum(a)
43.7 µs ± 1.71 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

可以看出,numba甚至比号称最接近C语言速度运行的numpy还要快6倍以上。但大家都知道,numpy往往对大的数组更加友好,那我们来测试一个更长的数组

a = np.linspace(0,100,10**6) # 创建一个长度为100万的数组

测试结果如下

# np.sum(a)
2.51 ms ± 246 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# sum(a)
249 ms ± 19.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# nb_sum(a)
3.01 ms ± 59.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# py_sum(a)
592 ms ± 42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

可见即便是用很长的loop来计算,numba的表现也丝毫不亚于numpy。在这里,我们可以看到numba相对于numpy一个非常明显的优势:numba可以把各种具有很大loop的函数加到很快的速度,但numpy的加速只适用于numpy自带的函数

但要注意的是,numba对没有循环或者只有非常小循环的函数加速效果并不明显,用不用都一样。(偷偷告诉你,numba的loop甚至常常比numpy的矩阵运算还要快)

兼容常用的科学计算包,可以创建ufunc

上一部分我们比较了numba和numpy的表现,可以说numba非常亮眼了。但numpy还有一个非常强大的功能——ufunc (universal functions),它可以让一个函数同时处理很多数据。比如要求一个数组每一个元素的三角函数,只需要

np.sin(a) # 这里的a仍然是上面有100万个元素的数组

而不需要写个循环一个一个求。可如果不用numpy但又想要很快的速度,那应该怎么求呢?我们可以用从math库里导入sin,然后写个loop再用numba加速。除了这个方法,在这里我还想说numba另一个强大的功能,矢量化(vectorize)。像上面的jit一样,只要添加一行vectorize就可以让普通函数变成ufunc

from math import sin@nb.vectorize()
def nb_vec_sin(a):return sin(a)

来比较一下用各种方式写出的三角函数

# 用numba加速的loop
13.5 ms ± 405 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# nb_vec_sin(a)
14.2 ms ± 55.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# np.sin(a)
5.75 ms ± 85 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

可以看出,用vectorize改写的三角函数具有了和np.sin()一样的同时处理数组每个元素的功能,而且表现也不必numpy差。当遇到numpy没有的数学函数时(比如sech),用numba矢量化不失为一个好的选择。除了math中的sin,它支持的其他函数列表可以在documentation中找到(链接见附录)。

其实numpy也有矢量化的功能,只不过比numba差远了。

会自动调整精度,保证准确性

上面我们用的测试数组数字范围只是从0到100的。可如果数字很大,那么就很容易出现overflow的问题,比如

a = np.arange(10**6) # a的最小值为0,最大值为10**6-1

你猜猜用python自带的sum,我们自己写的py_sum,np.sum和nb_sum给出的结果一不一样呢?你会发现

# np.sum(a)
1783293664
# sum(a)
1783293664
# nb_sum(a)
499999500000
# py_sum(a)
1783293664

numba的结果和其他三个都不一样,肯定错了呀,还用问么?

且慢!其实在运行的时候,我并没有告诉你sum和py_sum都报错了“RuntimeWarning: overflow encountered in long_scalars”。但奇怪的是np.sum并没有报错。

在上面的四个函数里,其实numba表现的最好,因为它自动调整了整数类型。如果你用nb.typeof()查看,你会发现numba给出的结果是int64,而其他三个都是int32。不得不说,numba不仅快还在精度方面表现很好

拓展

在本文的最后一部分,我想谈两个问题。

更多numba的加速选项

除了上面提到的jit和vectorize,其实numba还支持很多加速类型。常见的比如

​ @nb.jit(nopython=True,fastmath=True) 牺牲一丢丢数学精度来提高速度

​ @nb.jit(nopython=True,parallel=True) 自动进行并行计算

切记一定要用nopython。默认都是True的,但有时候如果定义的函数中遇到numba支持不良好的部分,它就会自动关闭nopython模式。没有nopython的numba就好像没有武器的士兵,虽然好过没兵,但确实没什么战斗力。因此,在使用jit时候要明确写出nopython=True。如果遇到问题,就找到这些支持不良好的部分,然后改写。毕竟numba对loop非常友好,改写这些部分应当是非常容易的。

其实如何选择这些模式会对函数有最佳的加速效果,是一个玄学。我前段时间向一位精通numba的prof请教,他给我的建议是,多试试就知道有没有用了。。。另外,numba还支持多个用GPU加速的包,比如CUDA。

Numba的精度问题

精度方面,在上面我也谈到numba会自动转换数据类型以适应计算。但是在个别时候,这种自动转变类型可能会引起一些计算误差。通常这个误差是非常小的,几乎不会造成任何影响。但如果你所处理的问题会积累误差,比如求解非线性方程,那么在非常多的计算之后误差可能就是肉眼可见了。如果你发现有这样的问题,记得在jit中指定输入输出的数据类型。numba具有C所有的数据类型,比如对上面的求和函数,只需要把@nb.jit()改为@nb.jit(nb.int64(nb.int32[:]))即可。nb.int64是说输出的数字为int64类型,nb.int32是说输入的数据类型为int32,而[:]是说输入的是数组。


附录

Numba documentation链接

https://numba.pydata.org/numba-doc/dev/index.html

速度比较:C, Julia, Python, Numba, Cython和LU Factorization

https://www.ibm.com/developerworks/community/blogs/jfp/entry/A_Comparison_Of_C_Julia_Python_Numba_Cython_Scipy_and_BLAS_on_LU_Factorization?lang=en

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

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

相关文章

服务概述

Android中的服务Service,和Activity不同的是不能与用户交互的,不能自己启动,系统的后台运行,当程序退出时,我们没有显示的调用停止服务,那么这个Service就没有结束,它仍然在后台运行。Service和…

[ZJOI2019]麻将

Luogu5279 , LOJ3042题意&#xff1a;给出初始13张手牌&#xff0c;求理论可以和牌的最小轮数的期望&#xff0e;定义和牌为&#xff1a;4句话1对乱将&#xff0c;不能有杠&#xff1b;七对 原始题解-shadowice 写得很好的题解 首先分析期望&#xff1a;\(<--\)所有和牌的步…

二进制搜索算法_二进制搜索的一个扭曲故事

二进制搜索算法by Divya Godayal通过Divya Godayal 二进制搜索的一个扭曲故事 (A twisted tale of Binary Search) Awesome. That’s how I feel right now. Writing my first solo tech article.太棒了 那就是我现在的感觉。 写我的第一篇个人技术文章。 I must say I have …

leetcode1221. 分割平衡字符串(贪心算法)

在一个「平衡字符串」中&#xff0c;‘L’ 和 ‘R’ 字符的数量是相同的。 给出一个平衡字符串 s&#xff0c;请你将它分割成尽可能多的平衡字符串。 返回可以通过分割得到的平衡字符串的最大数量。 示例 1&#xff1a; 输入&#xff1a;s “RLRRLLRLRL” 输出&#xff1a…

javascript中对变量类型的推断

本文正式地址&#xff1a;http://www.xiabingbao.com/javascript/2015/07/04/javascript-type 在JavaScript中&#xff0c;有5种基本数据类型和1种复杂数据类型&#xff0c;基本数据类型有&#xff1a;Undefined, Null, Boolean, Number和String。复杂数据类型是Object。Object…

U盘流畅运行linux发行版,做各种linux发行版的启动U盘方法

偶用tuxboot先移植gparted到16GB的U盘。然后裁剪N个iso 做成一个U盘安装或体验N个系统的多功能盘。选单晒出来&#xff1a;default vesamenu.c32timeout 3000prompt 0menu title Android RHEL6.4 Ubuntu13.04 GpartedMENU BACKGROUND Gsplash.pnglabel 001menu label GRUB4DOSk…

采样次数不同平均值不一样_不同的真石漆装饰效果也是不一样的

外墙真石漆真的是一件很好的产品&#xff0c;具有防火性、防水性、安全且环保、粘力强、永不褪色等特点&#xff0c;无疑是人们较好的选择&#xff0c;在很早之前就已经逐渐的取代了瓷砖和其他石材在人们心中的位置。真石漆的品种不止一种&#xff0c;按照装饰效果我们可以分为…

No-3.Linux 终端命令格式

Linux 终端命令格式 01. 终端命令格式 command [-options] [parameter]说明&#xff1a; command&#xff1a;命令名&#xff0c;相应功能的英文单词或单词的缩写[-options]&#xff1a;选项&#xff0c;可用来对命令进行控制&#xff0c;也可以省略parameter&#xff1a;传给命…

电子设计速成_Web设计速成课程:从一个非设计者到另一个

电子设计速成by Ali Spittel通过Ali Spittel Web设计速成课程&#xff1a;从一个非设计者到另一个 (A Web Design Crash Course: from one non-designer to another) I will preface this by saying that I’m not a professional designer. That being said, I like building…

android项目方法数超过65536的解决办法

2019独角兽企业重金招聘Python工程师标准>>> 当项目的总方法数超过65536个&#xff0c;运行在手机上&#xff0c;指不定会报找不到哪个文件的错。 我把项目的PullRefresh框架切换为SmartRefresh框架出现了方法数超过65536。 此文只是做一下笔记&#xff0c;不多做解…

leetcode1046. 最后一块石头的重量(堆)

有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出两块 最重的 石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#xff1a; 如果 x y&#xff0c;那么两块石头都会被完全…

[Linux]几个armhf的ubuntu源

摘自百度贴吧&#xff0c;留存 http://mirrors.ustc.edu.cn/ubuntu-ports/http://ftp.ubuntu-tw.org/mirror/ubuntu-ports/http://mirror.csclub.uwaterloo.ca/ubuntu-ports/http://mirrors.mit.edu/ubuntu-ports/ 速度从上到下越来越慢 中科技大 > 台湾新北 > 滑铁卢大学…

asp.net Linux 界面,在 ASP.NET 中实现不同角色的用户使用不同登录界面的方法

很多用户在开发 ASP.NET应用程序时都有这样的需求&#xff1a;管理员角色的账户使用管理员的登录界面进行登录&#xff0c;普通用户角色的账户使用普通用户的登录界面进行登录。由于ASP.NET的web.config里只能使用一个 authentication mode"Forms"节点&#xff0c;所…

pandas之Series

知识点 Pandas的数据类型有两种&#xff1a;1、Series 一维&#xff0c;带标签数组2、DataFrame 二维&#xff0c;Series容器Serial对象本质上由两个数组构成&#xff0c;一个数组构成对象的健(index,索引),一个数组构成对象的值(values).因此Series可以看作是键值对(健-->值…

python快乐数字怎么表达_Python经典面试题:这些面试题你会了吗?

前言什么&#xff1f;你要去找工作&#xff1f;先别急着找工作&#xff0c;先把下面的python面试题先给看了吧&#xff0c;不然你就只是去面试而不是找工作。话说不打没准备的仗&#xff0c;下面这些基本的面试题都不会你怎么可能找到工作呢&#xff1f;还是先把下面的东西1、P…

【swift学习笔记】三.使用xib自定义UITableViewCell

使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell&#xff0c;拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewcell上 并给我们的xib一个标识 为了学习&#xff0c;我这里的xib和后台的class是分开建的。我们再建一个cocoa touc…

leetcode455. 分发饼干(贪心算法)

假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。对每个孩子 i &#xff0c;都有一个胃口值 gi &#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j &#xff0c;都有一个尺寸 sj 。…

slack 使用说明_我如何使用Node和Botkit构建HR Slack Bot

slack 使用说明为什么要创建Slack Bot&#xff1f; (Why create a Slack Bot ?) I am an HR professional. More specifically I am a Human Resources Information System (HRIS) Consultant. I work with Application Tracking Systems, Learning Management Systems, and C…

linux 监听数据包,linux下网络监听与发送数据包的方法(即libpcap、libnet两种类库的使用方法)...

linux下可以用libpcap函数库实现监听数据包&#xff0c;使用libnet 函数库发送数据包安装:在命令行下apt-get install 就可以了libpcap的使用:/*author hjjdate 2011-1-21function:capture packet with the ruler and output the packet informationmodify 2011-1-23function:g…

命令模式(Command Pattern)

1命令模式是一个高内聚的模式。定义如下&#xff1a;将一个请求封装成一个对象&#xff0c;从而让你使用不同的请求把客户端参数化&#xff0c;对请求排队或者记录请求日志&#xff0c;可以提供命令的撤销和恢复功能。 2.角色说明&#xff1a; ● Receive接收者角色 该角色就…