Mã python có thể được biên dịch thành c không?

« Trước 1 2 3 Tiếp »

Python hiệu suất cao – Mã biên dịch và Giao diện C

Cython

Cython là một trình biên dịch tĩnh tối ưu hóa cho Python (Python2/Python3) và một ngôn ngữ lập trình mở rộng dựa trên Pyrex. (Ghi chú. Tốt hơn hết là bạn nên chuyển từ Python 2 sang Python 3 khá nhanh bởi vì, như Python wiki đã nói, “Python 2. x là di sản, Python 3. x là hiện tại và tương lai của ngôn ngữ. ”) Ngôn ngữ Pyrex được sử dụng để tạo các mô-đun Python. Nó thực sự là một superset của Python cũng hỗ trợ gọi các hàm C và khai báo các kiểu C trên các biến và thuộc tính lớp. Kết quả là, với một số công việc, mã C rất hiệu quả có thể được tạo ra

Không giống như Numba, một trình biên dịch JIT, Cython dịch mã Python sang C và biên dịch nó thành một dạng thích hợp để sử dụng trong Python. Nói chung, mã C biên dịch với hầu hết mọi trình biên dịch C/C++, điều này làm cho Cython trở thành một công cụ tốt để biên dịch mã Python được sử dụng thường xuyên nhưng không thay đổi quá nhiều

Ví dụ về Cython

Cython có thể chấp nhận hầu hết mọi tệp nguồn Python hợp lệ để tạo mã C. Biên dịch mã C khá đơn giản. Bước đầu tiên trong việc sử dụng Cython là dễ nhất. Chọn mã bạn muốn và đặt nó vào một tệp riêng. Bạn có thể có nhiều chức năng cho mỗi tệp nếu muốn

Bước thứ hai là tạo thiết lập. py, giống như tệp tạo tệp cho Python. Nó xác định tệp Python nào bạn muốn biên dịch thành thư viện có thể chia sẻ và là nơi bạn có thể đặt các tùy chọn (e. g. , tùy chọn biên dịch) bạn muốn sử dụng. Sau khi biên dịch, hãy nhớ kiểm tra mã

Ở đây, tôi sử dụng hai ví dụ từ hướng dẫn về Cython. Đầu tiên là một ví dụ Hello World đơn giản và thứ hai là một ví dụ tổng kết sử dụng một vòng lặp

Chào thế giới

Mã Python sẽ được biên dịch trong helloworld. tệp pyx là

print("Hello World")

đó chỉ là tập lệnh Python một dòng đơn giản nhất mà bạn có thể có

Như đã đề cập trước đây, bạn cần tạo thiết lập. py thực sự là một tệp thực hiện Python

from distutils.core import setup
from Cython.Build import cythonize
 
setup(
    ext_modules = cythonize("helloworld.pyx")
)

Hai dòng đầu tiên khá chuẩn cho thiết lập Python. tệp py. Sau đó, lệnh thiết lập xây dựng tệp nhị phân (đối tượng được chia sẻ). Trong trường hợp này, lệnh là cythonize helloworld. tệp pyx. Để làm cho cuộc sống dễ dàng hơn, hãy đảm bảo đặt tệp này vào cùng thư mục với mã

Hệ thống tôi đã sử dụng có Ubuntu 18. 04 (có cập nhật) và bản phân phối Anaconda Python. Để tạo nhị phân, hãy nhập

$ python3 setup.py build_ext --inplace

Đầu ra được hiển thị trong Liệt kê 3

Liệt kê 3. Bản dựng nhị phân

$ python3 setup.py build_ext --inplace
Compiling helloworld.py because it changed.
[1/1] Cythonizing helloworld.pyx
/home/laytonjb/anaconda3/lib/python3.7/site-packages/Cython/Compiler/Main.py:367: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /home/laytonjb/HPC-PYTHON-1/helloworld.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)
running build_ext
building 'helloworld' extension
creating build
creating build/temp.linux-x86_64-3.7
gcc -pthread -B /home/laytonjb/anaconda3/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/laytonjb/anaconda3/include/python3.7m -c helloworld.c -o build/temp.linux-x86_64-3.7/helloworld.o
gcc -pthread -shared -B /home/laytonjb/anaconda3/compiler_compat -L/home/laytonjb/anaconda3/lib -Wl,-rpath=/home/laytonjb/anaconda3/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.7/helloworld.o -o /home/laytonjb/HPC-PYTHON-1/helloworld.cpython-37m-x86_64-linux-gnu.so

Lưu ý rằng dòng lệnh sử dụng thiết lập. py là "cấu hình" để tạo tệp nhị phân (đối tượng dùng chung). Ở đầu ra, bạn sẽ thấy các đường dẫn tương ứng với hệ thống tôi đã sử dụng. Đừng lo lắng về điều này vì thiết lập. py xử lý các đường dẫn

Bây giờ tôi có thể kiểm tra đối tượng chia sẻ Cython đã biên dịch

>>> import helloworld
Hello World

Nó đã làm việc. Đây là các bước cơ bản để tạo mã nhị phân (đối tượng dùng chung) đã biên dịch của mã Python

tổng hợp

Để bắt đầu, tôi sẽ lấy một số mã Python đơn giản từ ví dụ Numba và tính tổng của danh sách một chiều. Mặc dù tôi chắc chắn rằng có mã tốt hơn để tính tổng, nhưng ví dụ này sẽ hướng dẫn bạn cách thực hiện một ví dụ toán học hơn

Đối với ví dụ này, một hàm đơn giản trong tổng. tệp pyx tính tổng

def sum(x):
  total = 0
  for i in range(x.shape[0]):
    total += x[i]
  return total

Mã này được biên dịch giống như mã Hello World, với sự thay đổi đối với hàm Python trong thiết lập. py để cythonize sum. pyx. Mã trong Liệt kê 4 kiểm tra mô-đun trong sổ ghi chép Jupyter

Liệt kê 4. Kiểm tra tổng kết

import sum
import numpy
x = numpy.arange(10_000_000);
%time sum.sum(x)
 
CPU times: user 1.37 s, sys: 0 ns, total: 1.37 s
Wall time: 1.37 s

Lưu ý rằng tổng là đối tượng và tổng. sum là hàm bên trong đối tượng, nghĩa là bạn có thể đặt nhiều hàm trong mã Python của mình. Cũng lưu ý rằng thời gian để chạy mã giống như Python thuần túy. Mặc dù bạn có thể tối ưu hóa mã Cython bằng cách sử dụng OpenMP chẳng hạn, tôi sẽ không thảo luận điều đó ở đây

công ty

Cython lấy mã Python, chuyển đổi nó thành C và biên dịch nó cho bạn, nhưng nếu bạn có sẵn mã C mà bạn muốn sử dụng trong Python như một mô-đun Python thì sao?

Thư viện hàm ngoại ctypes cung cấp các loại dữ liệu tương thích với C và cho phép bạn gọi các hàm trong thư viện liên kết động (DLL) hoặc thư viện dùng chung từ bên trong Python. Về bản chất, nó “bao bọc” các thư viện này để chúng có thể được gọi từ Python. Bạn có thể tìm thấy ctypes với hầu hết mọi bản phân phối Python

Để sử dụng ctypes, bạn thường bắt đầu với mã C/C++ của mình và tạo đối tượng có thể chia sẻ như bình thường. Tuy nhiên, hãy đảm bảo sử dụng cờ mã độc lập với vị trí (PIC) và cờ được chia sẻ (bạn sẽ xây dựng một thư viện). Ví dụ: với gcc, bạn sử dụng các tùy chọn -fPIC và -shared

$ gcc -fPIC -shared -o libsource.so source.c

Bạn có quyền biên dịch mã C và tạo thư viện bằng bất kỳ phương pháp nào bạn muốn, miễn là bạn sử dụng các tùy chọn -fPIC và -shared 

Ctypes Ví dụ – tổng hợp

Trong ví dụ trước, hầu hết công việc được thực hiện trong phần tổng kết, vì vậy bây giờ tôi sẽ viết lại quy trình đó trong C để có hiệu suất tốt hơn. Theo một hướng dẫn trực tuyến, một ví dụ bằng C để tính tổng và xây dựng nó thành một thư viện được hiển thị trong Liệt kê 5

Liệt kê 5. Tổng kết C

________số 8

Hàm được đặt tên là sum_function và mã sum. c. Mã này có thể được biên dịch thành đối tượng dùng chung (thư viện) với gcc

$ gcc -fPIC -shared -o libsum.so sum.c

Trình biên dịch tạo đối tượng dùng chung libsum. Vì vậy, một thư viện

Để sử dụng thư viện trong Python, cần có một vài hàm và biến ctypes cụ thể trong Python. Bởi vì nó có thể làm cho mã Python hơi phức tạp, nên tôi viết một “hàm bao bọc” cho thư viện bằng Python (Liệt kê 6)

Liệt kê 6. Chức năng trình bao bọc

from distutils.core import setup
from Cython.Build import cythonize
 
setup(
    ext_modules = cythonize("helloworld.pyx")
)
0

Lưu ý rằng hàm cụ thể sum_function được xác định. Nếu bạn có một thư viện có nhiều chức năng, bạn sẽ phải tạo giao diện cho từng chức năng trong tệp này

Bây giờ để kiểm tra hàm C trong Python

from distutils.core import setup
from Cython.Build import cythonize
 
setup(
    ext_modules = cythonize("helloworld.pyx")
)
1

Con đại bàng đã hạ cánh. nó hoạt động. Tuy nhiên, bạn có thể nhận thấy rằng nó chậm hơn cả mã Python thuần túy. Rất có thể cường độ số học không đủ lớn để cho thấy sự cải thiện. Đừng để điều này ngăn cản bạn. Bạn luôn nên dùng thử ctypes nếu muốn hoặc cần hiệu suất cao hơn

Làm cách nào để chuyển đổi mã Python thành mã C?

Chuyển mã Python sang C để tăng tốc .
%%cython -a def cy_fib(n). a = 0 b = 1 cho tôi trong phạm vi (n). a, b = a+b, a trả về a
%%cython -a cpdef double cy_fib(int n). cdef double a, b a = 0 b = 1 for i in range(n). a, b = a+b, a trả về a
%timeit py_fib(100) %timeit tê_fib(100) %timeit cy_fib(100)

Chương trình Python có thể biên dịch được không?

Mã nguồn Python được trình thông dịch CPython tự động biên dịch thành mã byte Python. Mã đã biên dịch thường được lưu trữ trong các tệp PYC (hoặc PYO) và được tạo lại khi nguồn được cập nhật hoặc khi cần thiết

Python có thể được biên dịch sang mã máy C hoặc một số ngôn ngữ khác không?

Vâng, Python là ngôn ngữ được biên dịch và thông dịch Khi nói đến C và C++ chúng là các ngôn ngữ được biên dịch bởi vì bạn, với tư cách là một lập trình viên, bạn . Điều này đơn giản có nghĩa là máy của bạn không thể hiểu những ngôn ngữ này.

Python có được biên dịch nhanh như C không?

Tuy nhiên, Python có một nhược điểm lớn. Nó chậm hơn nhiều so với các ngôn ngữ được biên dịch như C hoặc C++ .