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.pswp.cn/news/393786.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393786.shtml
英文地址,請注明出處:http://en.pswp.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接收者角色 該角色就…