Chọn một trang web để nhận nội dung đã dịch nếu có và xem các sự kiện và ưu đãi tại địa phương. Dựa trên vị trí của bạn, chúng tôi khuyên bạn nên chọn.
Bạn cũng có thể chọn một trang web từ danh sách sau
Làm thế nào để có được hiệu suất trang web tốt nhất
Chọn trang Trung Quốc [bằng tiếng Trung hoặc tiếng Anh] để có hiệu suất trang tốt nhất. Các trang web quốc gia khác của MathWorks không được tối ưu hóa cho các lượt truy cập từ vị trí của bạn
Cú pháp
>>> import helloworld Hello World7 cụ thể của Cython, được thiết kế để khai báo kiểu ngắn gọn và dễ đọc từ góc độ C/C++
Cú pháp Python thuần túy cho phép khai báo kiểu Cython tĩnh trong mã Python thuần túy , tuân theo gợi ý loại PEP-484 và chú thích biến PEP 526.
Để sử dụng các kiểu dữ liệu C trong cú pháp Python, bạn cần nhập mô-đun
>>> import helloworld Hello World8 đặc biệt trong mô-đun Python mà bạn muốn biên dịch, e. g
import cython
Nếu bạn sử dụng cú pháp Python thuần túy, chúng tôi thực sự khuyên bạn nên sử dụng bản phát hành Cython 3 gần đây, vì những cải tiến đáng kể đã được thực hiện ở đây so với phiên bản 0. 29. x phát hành
Khái niệm cơ bản về Cython¶
Bản chất cơ bản của Cython có thể được tóm tắt như sau. Cython là Python với kiểu dữ liệu C
Cython là Python. Hầu như bất kỳ đoạn mã Python nào cũng là mã Cython hợp lệ. [Có một vài Hạn chế , nhưng phép tính gần đúng này tạm thời. ] Trình biên dịch Cython sẽ chuyển đổi nó thành mã C để thực hiện các lệnh gọi tương đương với API Python/C.
Nhưng Cython còn hơn thế nữa, bởi vì các tham số và biến có thể được khai báo theo kiểu dữ liệu C. Mã thao tác giá trị Python và giá trị C có thể được tự do trộn lẫn với nhau, với các chuyển đổi diễn ra tự động bất cứ khi nào có thể. Bảo trì số lượng tham chiếu và kiểm tra lỗi của các hoạt động Python cũng tự động và toàn bộ sức mạnh của các phương tiện xử lý ngoại lệ của Python, bao gồm các câu lệnh thử ngoại trừ và thử cuối cùng, có sẵn cho bạn – ngay cả khi đang thao tác với dữ liệu C.
Cython Xin chào thế giới¶
Vì Cython có thể chấp nhận hầu hết mọi tệp nguồn python hợp lệ, một trong những điều khó nhất khi bắt đầu chỉ là tìm cách biên dịch tiện ích mở rộng của bạn
Vì vậy, hãy bắt đầu với con trăn kinh điển xin chào thế giới
print["Hello World"]
Lưu mã này vào tệp có tên
>>> import helloworld Hello World9. Bây giờ chúng ta cần tạo
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World0, giống như tệp Makefile của trăn [để biết thêm thông tin, hãy xem Tệp nguồn và trình biên dịch ].
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World0 của bạn sẽ trông giống như.
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]
Để sử dụng điều này để xây dựng tệp Cython của bạn, hãy sử dụng các tùy chọn dòng lệnh
________số 8
Điều này sẽ để lại một tệp trong thư mục cục bộ của bạn có tên là
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World2 trong unix hoặc
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World3 trong Windows. Bây giờ để sử dụng tập tin này. bắt đầu trình thông dịch python và chỉ cần nhập nó như thể nó là một mô-đun python thông thường
>>> import helloworld Hello World
Xin chúc mừng. Bây giờ bạn đã biết cách xây dựng tiện ích mở rộng Cython. Nhưng cho đến nay, ví dụ này không thực sự mang lại cảm giác tại sao một người lại muốn sử dụng Cython, vì vậy hãy tạo một ví dụ thực tế hơn
>>> import pyximport; pyximport.install[]
>>> import helloworld
Hello World
4. Biên dịch Cython dành cho nhà phát triển¶
Nếu mô-đun của bạn không yêu cầu bất kỳ thư viện C bổ sung nào hoặc thiết lập bản dựng đặc biệt, thì bạn có thể sử dụng mô-đun pyximport, do Paul Prescod phát triển ban đầu, để tải. pyx trực tiếp khi nhập mà không phải chạy tệp
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World0 của bạn mỗi khi bạn thay đổi mã của mình. Nó được vận chuyển và cài đặt với Cython và có thể được sử dụng như thế này
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World
Mô-đun Pyximport cũng có hỗ trợ biên dịch thử nghiệm cho các mô-đun Python bình thường. Điều này cho phép bạn tự động chạy Cython trên mọi. pyx và. py mà Python nhập vào, bao gồm thư viện chuẩn và các gói đã cài đặt. Cython vẫn sẽ không biên dịch được nhiều mô-đun Python, trong trường hợp đó, cơ chế nhập sẽ chuyển sang tải các mô-đun nguồn Python thay thế. Các. cơ chế nhập py được cài đặt như thế này.
>>> import helloworld Hello World5
Lưu ý rằng không nên để Pyximport mã xây dựng ở phía người dùng cuối khi mã này kết nối với hệ thống nhập của họ. Cách tốt nhất để phục vụ người dùng cuối là cung cấp các gói nhị phân dựng sẵn ở định dạng đóng gói bánh xe.
Fibonacci Fun¶
Từ hướng dẫn Python chính thức, một hàm fibonacci đơn giản được định nghĩa là
>>> import helloworld Hello World6
Bây giờ làm theo các bước cho ví dụ Hello World, trước tiên chúng ta đổi tên tệp để có một. pyx, giả sử là
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World6, sau đó chúng tôi tạo tệp
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World0. Sử dụng tệp được tạo cho ví dụ Hello World, tất cả những gì bạn cần thay đổi là tên của tên tệp Cython và tên mô-đun kết quả, làm như vậy chúng ta có
>>> import helloworld Hello World9
Xây dựng tiện ích mở rộng với cùng một lệnh được sử dụng cho helloworld. pyx
________số 8
Và sử dụng tiện ích mở rộng mới với
print["Hello World"]0
Số nguyên tố¶
Đây là một ví dụ nhỏ cho thấy một số điều có thể được thực hiện. Đó là một thói quen để tìm số nguyên tố. Bạn cho nó biết bạn muốn bao nhiêu số nguyên tố và nó trả về chúng dưới dạng danh sách Python
Python nguyên chấtCython
số nguyên tố. py ¶
print["Hello World"]1
print["Hello World"]2
số nguyên tố. pyx ¶
print["Hello World"]1
print["Hello World"]4
Bạn sẽ thấy rằng nó bắt đầu giống như một định nghĩa hàm Python bình thường, ngoại trừ tham số
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World8 được khai báo là kiểu
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World9. Điều này có nghĩa là đối tượng được truyền sẽ được chuyển đổi thành số nguyên C [hoặc
>>> import helloworld Hello World50 sẽ được nâng lên nếu không thể]
Bây giờ, hãy đi sâu vào cốt lõi của chức năng
Python nguyên chấtCython
print["Hello World"]5
print["Hello World"]6
print["Hello World"]7
print["Hello World"]8
Các dòng 2, 3, 11 và 12 sử dụng chú thích biến để xác định một số biến C cục bộ. Kết quả được lưu trữ trong mảng C
>>> import helloworld Hello World51 trong quá trình xử lý và sẽ được sao chép vào danh sách Python ở cuối [dòng 26]
print["Hello World"]5
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]0
Dòng 2 và 3 sử dụng câu lệnh
>>> import helloworld Hello World7 để xác định một số biến C cục bộ. Kết quả được lưu trữ trong mảng C
>>> import helloworld Hello World51 trong quá trình xử lý và sẽ được sao chép vào danh sách Python ở cuối [dòng 26]
Ghi chú
Bạn không thể tạo các mảng rất lớn theo cách này, bởi vì chúng được cấp phát trong lệnh gọi hàm C stack , đây là một lệnh khá quý giá và . Để yêu cầu các mảng lớn hơn hoặc thậm chí là các mảng có độ dài chỉ được biết khi chạy, bạn có thể tìm hiểu cách sử dụng hiệu quả Cấp phát bộ nhớ C , Python arrays or NumPy arrays with Cython.
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]1
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]2
Như trong C, khai báo một mảng tĩnh yêu cầu biết kích thước tại thời điểm biên dịch. Chúng tôi đảm bảo rằng người dùng không đặt giá trị trên 1000 [hoặc chúng tôi sẽ gặp lỗi phân đoạn, giống như trong C]
Python nguyên chấtCython
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]3
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]4
Khi chúng tôi chạy mã này từ Python, chúng tôi phải khởi tạo các mục trong mảng. Điều này được thực hiện dễ dàng nhất bằng cách điền nó bằng số 0 [như đã thấy ở dòng 8-9]. Mặt khác, khi chúng ta biên dịch cái này với Cython, mảng sẽ hoạt động như trong C. Nó được phân bổ trên ngăn xếp lệnh gọi hàm với độ dài cố định là 1000 mục chứa dữ liệu tùy ý từ lần cuối bộ nhớ đó được sử dụng. Sau đó, chúng tôi sẽ ghi đè lên các mục đó trong tính toán của chúng tôi
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]5
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]6
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]5
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]8
Các dòng 11-13 thiết lập một vòng lặp while sẽ kiểm tra các ứng cử viên số thành số nguyên tố cho đến khi tìm thấy số lượng số nguyên tố cần thiết
from setuptools import setup from Cython.Build import cythonize setup[ ext_modules = cythonize["helloworld.pyx"] ]9
$ python setup.py build_ext --inplace0
Các dòng 15-16, cố gắng chia một ứng cử viên cho tất cả các số nguyên tố được tìm thấy cho đến nay, được đặc biệt quan tâm. Bởi vì không có đối tượng Python nào được tham chiếu, vòng lặp được dịch hoàn toàn sang mã C và do đó chạy rất nhanh. Bạn sẽ nhận thấy cách chúng tôi lặp qua mảng
>>> import helloworld Hello World51 C
$ python setup.py build_ext --inplace1
$ python setup.py build_ext --inplace2
Vòng lặp được dịch thành vòng lặp C nhanh và hoạt động giống như lặp qua danh sách Python hoặc mảng NumPy. Nếu bạn không cắt mảng C bằng
>>> import helloworld Hello World55, thì Cython sẽ lặp qua 1000 phần tử của mảng
$ python setup.py build_ext --inplace3
$ python setup.py build_ext --inplace4
Nếu không xảy ra ngắt, điều đó có nghĩa là chúng tôi đã tìm thấy số nguyên tố và khối mã sau dòng 20 của
>>> import helloworld Hello World56 sẽ được thực thi. Chúng tôi thêm số nguyên tố được tìm thấy vào
>>> import helloworld Hello World51. Nếu bạn thấy có một
>>> import helloworld Hello World56 sau vòng lặp for là lạ, chỉ cần biết rằng đó là một tính năng ít được biết đến của ngôn ngữ Python và Cython sẽ thực thi nó ở tốc độ C cho bạn. Nếu cú pháp for-else làm bạn bối rối, hãy xem bài đăng trên blog tuyệt vời này
$ python setup.py build_ext --inplace5
$ python setup.py build_ext --inplace6
Ở dòng 26, trước khi trả về kết quả, chúng ta cần sao chép mảng C của mình vào danh sách Python, vì Python không đọc được mảng C. Cython có thể tự động chuyển đổi nhiều loại C từ và sang các loại Python, như được mô tả trong tài liệu về chuyển đổi loại , vì vậy chúng tôi có thể sử dụng cách hiểu danh sách đơn giản tại đây để . Bạn cũng có thể lặp lại thủ công trên mảng C và sử dụng
>>> import helloworld Hello World61, kết quả sẽ giống như vậy.
Bạn sẽ nhận thấy rằng chúng tôi khai báo một danh sách Python giống hệt như trong Python. Vì biến
>>> import helloworld Hello World62 chưa được khai báo rõ ràng với một loại, nên nó được giả định là chứa một đối tượng Python và từ phép gán, Cython cũng biết rằng loại chính xác là một danh sách Python
Cuối cùng, ở dòng 27, một câu lệnh return Python bình thường trả về danh sách kết quả
Python nguyên chấtCython
tổng hợp số nguyên tố. py với trình biên dịch Cython tạo ra một mô-đun mở rộng mà chúng ta có thể dùng thử trong trình thông dịch tương tác như sau
tổng hợp số nguyên tố. pyx với trình biên dịch Cython tạo ra một mô-đun mở rộng mà chúng ta có thể dùng thử trong trình thông dịch tương tác như sau
$ python setup.py build_ext --inplace7
Xem, nó hoạt động. Và nếu bạn tò mò về khối lượng công việc mà Cython đã tiết kiệm cho bạn, hãy xem mã C được tạo cho mô-đun này
Cython có một cách để trực quan hóa nơi diễn ra tương tác với các đối tượng Python và C-API của Python. Đối với điều này, hãy chuyển tham số
>>> import helloworld Hello World63 cho
>>> import helloworld Hello World64. Nó tạo ra một tệp HTML. Hãy xem nào
Python nguyên chấtCython
Nếu một dòng màu trắng, điều đó có nghĩa là mã được tạo không tương tác với Python, vì vậy sẽ chạy nhanh như mã C bình thường. Màu vàng càng đậm thì càng có nhiều tương tác Python trong dòng đó. Những dòng màu vàng đó thường sẽ hoạt động trên các đối tượng Python, đưa ra các ngoại lệ hoặc thực hiện các loại hoạt động cấp cao hơn những gì có thể dễ dàng dịch sang mã C đơn giản và nhanh chóng. Việc khai báo và trả về hàm sử dụng trình thông dịch Python nên các dòng đó có màu vàng là hợp lý. Tương tự đối với việc hiểu danh sách vì nó liên quan đến việc tạo đối tượng Python. Nhưng dòng
>>> import helloworld Hello World65, tại sao?
Chúng tôi có thể thấy rằng một số kiểm tra xảy ra. Vì Cython mặc định hành vi của Python nên ngôn ngữ này sẽ thực hiện kiểm tra phép chia trong thời gian chạy, giống như Python đã làm. Bạn có thể hủy kích hoạt các kiểm tra đó bằng cách sử dụng chỉ thị trình biên dịch .
Bây giờ hãy xem liệu chúng ta có tăng tốc độ ngay cả khi có kiểm tra bộ phận không. Hãy viết cùng một chương trình, nhưng bằng Python
primes_python. py / primes_python_compiled. py ¶
$ python setup.py build_ext --inplace8
Có thể lấy một tệp
>>> import helloworld Hello World66 đơn giản [không được chú thích] và biên dịch nó bằng Cython. Hãy tạo một bản sao của
>>> import helloworld Hello World67 và đặt tên là
>>> import helloworld Hello World68 để có thể so sánh nó với mô-đun Python [không được biên dịch]. Sau đó, chúng tôi biên dịch tệp đó bằng Cython mà không thay đổi mã. Bây giờ
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World0 trông như thế này
Python nguyên chấtCython
$ python setup.py build_ext --inplace9
>>> import helloworld Hello World0
Bây giờ chúng ta có thể đảm bảo rằng hai chương trình đó xuất ra các giá trị giống nhau
>>> import helloworld Hello World1
Có thể so sánh tốc độ bây giờ
>>> import helloworld Hello World2
Phiên bản cythonize của
>>> import helloworld Hello World67 nhanh hơn 2 lần so với phiên bản Python mà không thay đổi một dòng mã nào. Phiên bản Cython nhanh hơn 13 lần so với phiên bản Python. Điều gì có thể giải thích điều này?Nhiều thứ
Trong chương trình này, rất ít tính toán xảy ra ở mỗi dòng. Vì vậy, chi phí hoạt động của trình thông dịch python là rất quan trọng. Sẽ rất khác nếu bạn tính toán nhiều ở mỗi dòng. Sử dụng NumPy chẳng hạn
Vị trí dữ liệu. Có khả năng sẽ có nhiều thứ hơn có thể phù hợp với bộ đệm CPU khi sử dụng C so với khi sử dụng Python. Bởi vì mọi thứ trong python là một đối tượng và mọi đối tượng được triển khai dưới dạng từ điển, nên điều này không thân thiện lắm với bộ đệm
Thông thường tốc độ tăng từ 2x đến 1000x. Nó phụ thuộc vào mức độ bạn gọi trình thông dịch Python. Như mọi khi, hãy nhớ lập hồ sơ trước khi thêm các loại ở mọi nơi. Việc thêm các loại làm cho mã của bạn khó đọc hơn, vì vậy hãy sử dụng chúng một cách có chừng mực
Số nguyên tố với C++¶
Với Cython, cũng có thể tận dụng lợi thế của ngôn ngữ C++, đáng chú ý là một phần của thư viện chuẩn C++ có thể nhập trực tiếp từ mã Cython
Hãy xem mã của chúng ta sẽ như thế nào khi sử dụng vector từ thư viện chuẩn C++
Ghi chú
Vector trong C++ là cấu trúc dữ liệu triển khai danh sách hoặc ngăn xếp dựa trên mảng C có thể thay đổi kích thước. Nó tương tự như loại
>>> import helloworld Hello World91 của Python trong mô-đun thư viện chuẩn
>>> import helloworld Hello World91. Có sẵn một phương thức dự trữ sẽ tránh được các bản sao nếu bạn biết trước có bao nhiêu phần tử bạn sẽ đưa vào vectơ. Để biết thêm chi tiết xem trang này từ cppreference
Python nguyên chấtCython
>>> import helloworld Hello World3
>>> import helloworld Hello World4
Cảnh báo
Mã được cung cấp ở trên / trên trang này sử dụng thư viện gốc bên ngoài [không phải Python] thông qua
>>> import helloworld Hello World93 [
>>> import helloworld Hello World94]. Quá trình biên dịch Cython cho phép điều này, nhưng không có hỗ trợ nào cho điều này từ Python thuần túy. Cố gắng chạy mã này từ Python [không biên dịch] sẽ không thành công khi truy cập thư viện bên ngoài. Điều này được mô tả chi tiết hơn trong Gọi hàm C .
>>> import helloworld Hello World3
>>> import helloworld Hello World6
Dòng đầu tiên là chỉ thị của trình biên dịch. Nó yêu cầu Cython biên dịch mã của bạn thành C++. Điều này sẽ cho phép sử dụng các tính năng của ngôn ngữ C++ và thư viện chuẩn C++. Lưu ý rằng không thể biên dịch mã Cython thành C++ bằng pyximport. Bạn nên sử dụng
>>> import pyximport; pyximport.install[] >>> import helloworld Hello World0 hoặc sổ ghi chép để chạy ví dụ này
Bạn có thể thấy rằng API của vectơ tương tự như API của danh sách Python và đôi khi có thể được sử dụng làm thay thế thả xuống trong Cython