cpython的使用


這個的學習主要是因為在運行目標檢測的代碼時總是會出現下面的錯誤:

        from Cython.Build import cythonize
    ModuleNotFoundError: No module named 'Cython'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

安裝:

pip install Cython
Collecting Cython
  Downloading Cython-0.29.19-cp37-cp37m-macosx_10_9_x86_64.whl (1.9 MB)

 

所以打算學學這個模塊是怎么用的,以及用在哪里的

https://github.com/Sean16SYSU/CPython-Tutorial-zh

Python有時候太慢,如果手動編譯C或者是C++來寫#include<Python.h>的文件也比較麻煩。 CPython無疑是一個比較好的選擇。

 

改進的理由

  1. 每一行的計算量很少,因此python解釋器的開銷就會變的很重要。
  2. 數據的局部性原理:很可能是,當使用C的時候,更多的數據可以塞進CPU的cache中,因為Python的元素都是Object,而每個Object都是通過字典實現的,cache對這個數據不很友好。

 

項目

Hello World項目

第一個項目是Hello world。

創建一個文件helloworld.pyx,內容如下:

print("Hello world!")

保存后,創建setup.py文件,內容如下:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("helloworld.pyx")
)

保存后,命令行進入setup.py所在目錄,並輸入python setup.py build_ext --inplace,如下:

$python setup.py build_ext --inplace
Compiling helloworld.pyx because it changed.
[1/1] Cythonizing helloworld.pyx
/anaconda3/envs/deeplearning/lib/python3.7/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /Users/user/pytorch/NLP學習/learning_2.0/helloworld.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)
running build_ext
building 'helloworld' extension
creating build
creating build/temp.macosx-10.9-x86_64-3.7
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/anaconda3/envs/deeplearning/include -arch x86_64 -I/anaconda3/envs/deeplearning/include -arch x86_64 -I/anaconda3/envs/deeplearning/include/python3.7m -c helloworld.c -o build/temp.macosx-10.9-x86_64-3.7/helloworld.o
gcc -bundle -undefined dynamic_lookup -L/anaconda3/envs/deeplearning/lib -arch x86_64 -L/anaconda3/envs/deeplearning/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.9-x86_64-3.7/helloworld.o -o /Users/user/pytorch/NLP學習/learning_2.0/helloworld.cpython-37m-darwin.so

運行完這個命令后,該目錄下就會生成三個文件:

build                    helloworld.pyx
helloworld.c                setup.py
helloworld.cpython-37m-darwin.so

然后創建一個調用文件test.py,內容為:

import helloworld

運行返回:

i$ python test.py 
Hello world!

 

.pyx文件:

pyx文件是python的c擴展文件,代碼要符合cython的規范,用什么編輯器寫都行。我在eric4上寫的,結果它默認用python解釋器來進行解釋,還提示有bug,“語法錯誤”。

 

上面的pyx文件還僅僅是源代碼文件,要想被python調用、要想運行,僅僅寫了源代碼還是不夠的(不像 Python 語言可直接解釋使用的 .py 文件,.pyx 文件必須先被編譯成 .c 文件,再編譯成 .pyd (Windows 平台) 或 .so (Linux 平台) 文件,才可作為模塊 import 導入使用)。具體來說,還要轉成.c或者.c++的文件,並且再進一步轉成.pyd文件。pyd文件才是可以直接使用的文件。為了達到上述目的,就要寫一個setup.py腳本,如上面那種

上述兩個步驟,相當於把某個python效率瓶頸模塊(這之前需要用profile工具來定位)用效率更高的代碼寫成了python的c擴展形式,接下來,就是要在python代碼中調用他們。test.py就是這個調用的腳本

 

Fibonacci Function項目

斐波那契數列:1, 1, 2, 3, 5,... 前兩位為1,之后每個數等於前面兩個數之和。

創建fib.pyx,內容如下:

from __future__ import print_function

def fib(n):
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

創建setup.py文件,內容如下:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("fib.pyx")
)

通過命令python setup.py build_ext --inplace,生成出來的文件:

python setup.py build_ext --inplace
Compiling fib.pyx because it changed.
[1/1] Cythonizing fib.pyx
/anaconda3/envs/deeplearning/lib/python3.7/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /Users/user/pytorch/NLP學習/learning_2.0/fib.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)
running build_ext
building 'fib' extension
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/anaconda3/envs/deeplearning/include -arch x86_64 -I/anaconda3/envs/deeplearning/include -arch x86_64 -I/anaconda3/envs/deeplearning/include/python3.7m -c fib.c -o build/temp.macosx-10.9-x86_64-3.7/fib.o
gcc -bundle -undefined dynamic_lookup -L/anaconda3/envs/deeplearning/lib -arch x86_64 -L/anaconda3/envs/deeplearning/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.9-x86_64-3.7/fib.o -o /Users/user/pytorch/NLP學習/learning_2.0/fib.cpython-37m-darwin.so

測試test.py:

import fib
fib.fib(100)

返回:

$ python test.py 
1 1 2 3 5 8 13 21 34 55 89 

如果輸出兩者的時間:

(deeplearning) userdeMacBook-Pro:learning_2.0 user$ python fib.pyx 
1 1 2 3 5 8 13 21 34 55 89 
5.7220458984375e-05
(deeplearning) userdeMacBook-Pro:learning_2.0 user$ python test.py 
1 1 2 3 5 8 13 21 34 55 89 
5.793571472167969e-05

發現速度並沒有很高的提升,很可能是操作本來就很簡單,數值也很小,沒什么優化的空間了。

 

Primes項目

給一個數值n,輸出前n個質數(list)。

寫到primes.pyx中:

def primes(int nb_primes):
    cdef int n, i, len_p
    cdef int p[1000]
    if nb_primes > 1000:
        nb_primes = 1000

    len_p = 0
    n = 2
    while len_p < nb_primes:
        for i in p[:len_p]:
            if n % i == 0:
                break
        else:
            p[len_p] = n
            len_p += 1
        n += 1
    result_as_list = [prime for prime in p[:len_p]]
    return result_as_list

setup.py:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("primes.pyx")
)

test.py:

import primes
import time

time0 = time.time()
primes.primes(10000)
print(time.time() - time0)

返回使用時間:

0.0017080307006835938
View Code

 

prime.py原來:

def primes(nb_primes):
    p = []
    if nb_primes > 1000:
        nb_primes = 1000

    n = 2
    while len(p) < nb_primes:
        for i in p:
            if n % i == 0:
                break
        else:
            p.append(n)
        n += 1
    result_as_list = [prime for prime in p]
    return result_as_list

if __name__ == '__main__':
    import time
    time0 = time.time()
    primes(10000)
    print(time.time() - time0)

使用時間:

0.030839204788208008

可見的確快了不少!!!!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM