欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

利用 Numba 加速 Python 程序,提速幾十倍

系統 1959 0

作者:chen_h
微信號 & QQ:862251340
微信公眾號:coderpai


當你嫌棄 Python 速度慢時

Python編程語言幾乎可用于任何類型的快速原型設計和快速開發。它具有很強的功能,例如它的高級特性,具有幾乎人性化可讀性的語法。此外,它是跨平臺的,具有多樣性的標準庫,它是多范式的,為程序員提供了很多自由,可以使用不同的編程范例,如面向對象,功能或者程序。但是,有時我們系統的某些部分具有高性能要求,因此 Python 提供的速度可能遠遠不夠,那么,我們如何在不離開 Python 領域的情況下提高性能。

其中一個可能的解決方案是使用 Numba,這是一種將 Python 代碼轉換為機器指令的運行編輯器,同時讓我們使用 Python 的簡潔和表達能力,并實現機器碼的速度。

什么是 Numba?

Numba 是一個執行 JIT 編譯的庫,即使用 LLVM 行業標準編譯器在運行時將純 Python 代碼轉換為優化的機器代碼。它還能夠自動并行化在多個核上面運行代碼。Numba 是跨平臺的,因為它適用于不同的操作系統(Linux,Windows,OSX)和不同的架構(x86,x86_64,ppc64le等等)。它還能夠在GPU(NVIDIA CUDA 或者 AMD ROC)上運行相同的代碼,并與 Python 2.7 和 3.4-3.7兼容??偟膩碚f,最令人印象深刻的功能是它的使用簡單,因為我們只需要一些裝飾器來充分利用 JIT 的全部功能。

Numba模式和 @jit 裝飾器

最重要的指令是 @jit 裝飾器。正是這個裝飾器指示編譯器運行哪種模式以及使用什么配置。在這種配置下,我們的裝飾函數的生成字節碼與我們在裝飾器中指定的參數(例如輸入參數的類型)相結合,進行分析,優化,最后使用 LLVM 進行編譯,生成特定定制的本機機器指令。然后,為每個函數調用此編譯版本。

有兩種重要的模式:nopython和object。noPython 完全避免了 Python 解釋器,并將完整代碼轉換為可以在沒有 Python 幫助的情況下運行的本機指令。但是,如果由于某種原因,該模式不可用(例如,當使用不受支持的 Python功能或者外部庫時),編譯將回退到對象模式,當它無法編譯某些代碼時,它將使用 Python 解釋器。當然,nopython 模式是提供最佳性能提升的模式。

Numba 的高層架構

Numba 的轉換過程可以在一系列重要步驟中進行轉換,從字節碼分析到最終機器代碼生成。下面的圖片說明了這個過程,其中綠色框對應于 Numba 編譯器的前端,藍色框屬于后端。

利用 Numba 加速 Python 程序,提速幾十倍_第1張圖片

Numba 編譯器首先對所需函數的 byecode 進行分析。此步驟生成一個描述可能的執行流程的圖表,稱為控制流程圖(CFG)?;谠搱D,我們就可以計算分析整個過程。完成這些步驟后,編譯器開始將字節碼轉換為中間表示(IR),Numba 將執行進一步的優化和轉換。然后,執行類型推斷,這是最重要的步驟之一。在此步驟中,編譯器將嘗試推斷所有變量的類型。此外,如果啟用并行設置,IR 代碼將轉換為等效的并行版本。

如果成功推斷出所有類型,則將 Numba IR代碼轉換為有效的 LLVM IR 代碼。但是,如果類型推斷過程失敗,LLVM 生成的代碼將會變慢,因為它仍然需要處理對 Python C API 的調用。最后,LLVM IR 代碼由 LLVM JIT 編譯器編譯為本機指令。然后將這個優化的加工代碼加載到內存中,并在對同一函數的多次調用中重用,使其比純 Python 快數百倍。

出于調試目的,Numba 還提供了一組可以啟用的標志,以便查看不同階段的輸出。

            
              os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DUMP_CFG"
              
              
                ]
              
              
                =
              
              
                "1"
              
              
os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DUMP_IR"
              
              
                ]
              
              
                =
              
              
                "1"
              
              
os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DUMP_ANNOTATION"
              
              
                ]
              
              
                =
              
              
                "1"
              
              
os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DEBUG_ARRAY_OPT_STATS"
              
              
                ]
              
              
                =
              
              
                "1"
              
              
os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DUMP_LLVM"
              
              
                ]
              
              
                =
              
              
                "1"
              
              
os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DUMP_OPTIMIZED"
              
              
                ]
              
              
                =
              
              
                "1"
              
              
os
              
                .
              
              environ
              
                [
              
              
                "NUMBA_DUMP_ASSEMBLY"
              
              
                ]
              
              
                =
              
              
                "1"
              
            
          

加速運算的一個例子

我們可以使用 Numba 庫的一個絕佳例子是進行密集的數值運算。舉個例子,讓我們計算一組 2 16 2^{16} 2 1 6 個隨機數的 softmax 函數。softmax 函數,用于將一組實際值轉換為概率并通常用作神經網絡體系結構中的最后一層,定義為:

利用 Numba 加速 Python 程序,提速幾十倍_第2張圖片

下面的代碼顯示了這個函數的兩個不同的實現,一個純 Python 方法,一個使用 numba 和 numpy 的優化版本:

            
              
                import
              
               time

              
                import
              
               math

              
                import
              
               numpy 
              
                as
              
               np

              
                from
              
               numba 
              
                import
              
               jit


@jit
              
                (
              
              
                "f8(f8[:])"
              
              
                ,
              
               cache
              
                =
              
              
                False
              
              
                ,
              
               nopython
              
                =
              
              
                True
              
              
                ,
              
               nogil
              
                =
              
              
                True
              
              
                ,
              
               parallel
              
                =
              
              
                True
              
              
                )
              
              
                def
              
              
                esum
              
              
                (
              
              z
              
                )
              
              
                :
              
              
                return
              
               np
              
                .
              
              
                sum
              
              
                (
              
              np
              
                .
              
              exp
              
                (
              
              z
              
                )
              
              
                )
              
              


@jit
              
                (
              
              
                "f8[:](f8[:])"
              
              
                ,
              
               cache
              
                =
              
              
                False
              
              
                ,
              
               nopython
              
                =
              
              
                True
              
              
                ,
              
               nogil
              
                =
              
              
                True
              
              
                ,
              
               parallel
              
                =
              
              
                True
              
              
                )
              
              
                def
              
              
                softmax_optimized
              
              
                (
              
              z
              
                )
              
              
                :
              
              
    num 
              
                =
              
               np
              
                .
              
              exp
              
                (
              
              z
              
                )
              
              
    s 
              
                =
              
               num 
              
                /
              
               esum
              
                (
              
              z
              
                )
              
              
                return
              
               s



              
                def
              
              
                softmax_python
              
              
                (
              
              z
              
                )
              
              
                :
              
              
    s 
              
                =
              
              
                [
              
              
                ]
              
              

    exp_sum 
              
                =
              
              
                0
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                len
              
              
                (
              
              z
              
                )
              
              
                )
              
              
                :
              
              
        exp_sum 
              
                +=
              
               math
              
                .
              
              exp
              
                (
              
              z
              
                [
              
              i
              
                ]
              
              
                )
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                len
              
              
                (
              
              z
              
                )
              
              
                )
              
              
                :
              
              
        s 
              
                +=
              
              
                [
              
              math
              
                .
              
              exp
              
                (
              
              z
              
                [
              
              i
              
                ]
              
              
                )
              
              
                /
              
               exp_sum
              
                ]
              
              
                return
              
               s



              
                def
              
              
                main
              
              
                (
              
              
                )
              
              
                :
              
              
    np
              
                .
              
              random
              
                .
              
              seed
              
                (
              
              
                0
              
              
                )
              
              
    z 
              
                =
              
               np
              
                .
              
              random
              
                .
              
              uniform
              
                (
              
              
                0
              
              
                ,
              
              
                10
              
              
                ,
              
              
                10
              
              
                **
              
              
                8
              
              
                )
              
              
                # generate random floats in the range [0,10)
              
              

    start 
              
                =
              
               time
              
                .
              
              time
              
                (
              
              
                )
              
              
    softmax_python
              
                (
              
              z
              
                .
              
              tolist
              
                (
              
              
                )
              
              
                )
              
              
                # run pure python version of softmax
              
              
    elapsed 
              
                =
              
               time
              
                .
              
              time
              
                (
              
              
                )
              
              
                -
              
               start
    
              
                print
              
              
                (
              
              
                'Ran pure python softmax calculations in {} seconds'
              
              
                .
              
              
                format
              
              
                (
              
              elapsed
              
                )
              
              
                )
              
              

    softmax_optimized
              
                (
              
              z
              
                )
              
              
                # cache jit compilation
              
              
    start 
              
                =
              
               time
              
                .
              
              time
              
                (
              
              
                )
              
              
    softmax_optimized
              
                (
              
              z
              
                )
              
              
                # run optimzed version of softmax
              
              
    elapsed 
              
                =
              
               time
              
                .
              
              time
              
                (
              
              
                )
              
              
                -
              
               start
    
              
                print
              
              
                (
              
              
                '\nRan optimized softmax calculations in {} seconds'
              
              
                .
              
              
                format
              
              
                (
              
              elapsed
              
                )
              
              
                )
              
              
                if
              
               __name__ 
              
                ==
              
              
                '__main__'
              
              
                :
              
              
    main
              
                (
              
              
                )
              
            
          

上述腳本的輸出結果為:

            
              Ran pure python softmax calculations 
              
                in
              
              
                77.56219696998596
              
               seconds

Ran optimized softmax calculations 
              
                in
              
              
                1.517017126083374
              
               seconds

            
          

這些結果清楚的顯示了將代碼轉換為 Numba 能夠理解的代碼時獲得的性能提升。

在 softmax_optimized 函數中,已經存在 Numba 注釋,它充分利用了 JIT 優化的全部功能。事實上,在編譯過程中,以下字節碼將被分析,優化并編譯為本機指令:

            
              
                >
              
               python

              
                import
              
               dis

              
                from
              
               softmax 
              
                import
              
               esum
              
                ,
              
               softmax_optimized

              
                >>
              
              
                >
              
               dis
              
                .
              
              dis
              
                (
              
              softmax_optimized
              
                )
              
              
                14
              
              
                0
              
               LOAD_GLOBAL              
              
                0
              
              
                (
              
              np
              
                )
              
              
                2
              
               LOAD_ATTR                
              
                1
              
              
                (
              
              exp
              
                )
              
              
                4
              
               LOAD_FAST                
              
                0
              
              
                (
              
              z
              
                )
              
              
                6
              
               CALL_FUNCTION            
              
                1
              
              
                8
              
               STORE_FAST               
              
                1
              
              
                (
              
              num
              
                )
              
              
                15
              
              
                10
              
               LOAD_FAST                
              
                1
              
              
                (
              
              num
              
                )
              
              
                12
              
               LOAD_GLOBAL              
              
                2
              
              
                (
              
              esum
              
                )
              
              
                14
              
               LOAD_FAST                
              
                0
              
              
                (
              
              z
              
                )
              
              
                16
              
               CALL_FUNCTION            
              
                1
              
              
                18
              
               BINARY_TRUE_DIVIDE
             
              
                20
              
               STORE_FAST               
              
                2
              
              
                (
              
              s
              
                )
              
              
                16
              
              
                22
              
               LOAD_FAST                
              
                2
              
              
                (
              
              s
              
                )
              
              
                24
              
               RETURN_VALUE

              
                >>
              
              
                >
              
               dis
              
                .
              
              dis
              
                (
              
              esum
              
                )
              
              
                9
              
              
                0
              
               LOAD_GLOBAL              
              
                0
              
              
                (
              
              np
              
                )
              
              
                2
              
               LOAD_ATTR                
              
                1
              
              
                (
              
              
                sum
              
              
                )
              
              
                4
              
               LOAD_GLOBAL              
              
                0
              
              
                (
              
              np
              
                )
              
              
                6
              
               LOAD_ATTR                
              
                2
              
              
                (
              
              exp
              
                )
              
              
                8
              
               LOAD_FAST                
              
                0
              
              
                (
              
              z
              
                )
              
              
                10
              
               CALL_FUNCTION            
              
                1
              
              
                12
              
               CALL_FUNCTION            
              
                1
              
              
                14
              
               RETURN_VALUE

            
          

我們可以通過簽名提供有關預期輸入和輸出類型的更多信息。在上面的示例中,簽名"f8[:](f8[:])" 用于指定函數接受雙精度浮點數組并返回另一個 64 位浮點數組。

簽名也可以使用顯式類型名稱:“float64 [:](float64 [:])”。一般形式是類型(類型,類型,…),類似于經典函數,其中參數名稱由其類型替換,函數名稱由其返回類型替換。Numba 接受許多不同的類型,如下所述:

Type name(s) Type short name Description
boolean b1 represented as a byte
uint8, byte u1 8-bit unsigned byte
uint16 u2 16-bit unsigned integer
uint32 u4 32-bit unsigned integer
uint64 u8 64-bit unsigned integer
int8, char i1 8-bit signed byte
int16 i2 16-bit signed integer
int32 i4 32-bit signed integer
int64 i8 64-bit signed integer
intc C
uintc C
intp pointer-sized integer
uintp pointer-sized unsigned integer
float32 f4 single-precision floating-point number
float64, double f8 double-precision floating-point number
complex64 c8 single-precision complex number
complex128 c16 double-precision complex number

這些注釋很容易使用 [:],[: , :] 或者 [: , : , ;] 分別擴展為數組形式,分別用于 1,2和3維。

最后

Python 是一個非常棒的工具。但是,它也有一些限制,但是我們可以通過一些別的途徑來提高它的性能,本文介紹的 Nubma 就是一種非常好的方式。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 999久久久国产精品 成人不卡视频 | 在线观看欧美成人 | 欧美日本一区 | 久久久久女人精品毛片 | 日本久久精品免视看国产成人 | 免费永久欧美性色xo影院 | 久久免费看少妇高潮A片JA小说 | 福利视频第一页 | 精品久久久网站 | 亚洲精品视频在线 | 久久丁香 | 国产成人精品久久亚洲高清不卡 | 一区二区三区日本在线观看 | 全黄性性激高免费视频 | 男女日比 | 欧洲成人午夜免费大片 | 欧美成人精品一区二区三区 | 亚洲人成网站在线在线 | 天天夜夜操 | 午夜性色一区二区三区不卡视频 | 国产成人一区二区三区 | 欧美 日韩 | 五月婷六月丁香狠狠躁狠狠爱 | 色中色综合网 | 9l蝌蚪porny中文自拍 | 日韩不卡高清 | 亚洲视频区 | 91短视频版在线观看www免费 | 免费一级在线 | 成人久久久久爱 | av 一区二区三区 | concern超碰在线 | 人人干人人干人人干 | 国产激情视频 | 欧美视频在线观看一区二区 | 欧美一区二区三区在线观看视频 | av网址在线播放 | 欧美一级日韩 | jdav视频在线观看免费 | 91亚洲国产成人久久精品网站 | 日本欧美一区二区三区视频 |