Cập nhật và vận hành với PyPy, một giải pháp thay thế cho CPython sử dụng biên dịch JIT.
Ngôn ngữ lập trình Python là một giao diện hoàn toàn có thể được tiến hành theo nhiều cách. Một số ví dụ gồm có CPython sử dụng ngôn từ C, Jython được tiến hành bằng Java, v.v.
Mặc dù phổ cập nhất, CPython không phải là nhanh nhất. PyPy là một tiến hành Python thay thế sửa chữa vừa tuân thủ vừa nhanh gọn. PyPy phụ thuộc vào vào quy trình biên dịch đúng lúc ( JIT ) giúp giảm đáng kể thời hạn thực thi cho những hoạt động giải trí chạy dài .
Trong hướng dẫn này, PyPy sẽ được ra mắt cho người mới khởi đầu để làm điển hình nổi bật nó khác với CPython như thế nào. Chúng tôi cũng sẽ đề cập đến những ưu điểm và hạn chế của nó. Sau đó, tất cả chúng ta sẽ xem xét cách tải xuống và sử dụng PyPy để thực thi một tập lệnh Python đơn thuần. PyPy tương hỗ hàng trăm thư viện Python, gồm có cả NumPy .
Cụ thể, hướng dẫn này bao gồm những điều sau:
Bạn đang đọc: Bắt đầu với PyPy
- Tổng quan nhanh về CPython
- Giới thiệu về PyPy và các tính năng của nó
- Hạn chế của PyPy
- Chạy PyPy trên Ubuntu
- Thời gian thực thi của PyPy vs CPython
Từ Unsplash bởi Clément H: https://unsplash.com/photos/95YRwf6CNw8
Tổng quan nhanh về CPython
Trước khi tranh luận về PyPy, điều quan trọng là phải biết CPython hoạt động giải trí như thế nào. Hướng dẫn trước đây của tôi có tiêu đề Tăng cường Tập lệnh Python Với Cython đã trình làng dài hơn về cách CPython hoạt động giải trí, nhưng sẽ không có hại gì nếu có một bản tóm tắt nhanh ở đây về những điểm quan trọng. Dưới đây, bạn hoàn toàn có thể thấy hình ảnh trực quan về quy trình tiến độ thực thi của một tập lệnh Python được tiến hành bằng CPython .
Với một .py
tập lệnh Python, mã nguồn lần đầu tiên được biên dịch bằng trình biên dịch CPython thành bytecode. Mã bytecode được tạo và lưu trong tệp có .pyc
phần mở rộng. Sau đó, mã bytecode được thực thi bằng trình thông dịch CPython trong môi trường ảo.
Có những quyền lợi khi sử dụng trình biên dịch để quy đổi mã nguồn thành bytecode. Nếu không có trình biên dịch nào được sử dụng, thì trình thông dịch sẽ thao tác trực tiếp trên mã nguồn bằng cách dịch từng dòng một sang mã máy. Điểm bất lợi của việc làm này là 1 số ít quá trình phải được vận dụng để dịch từng dòng mã nguồn thành mã máy và những tiến trình như vậy sẽ được lặp lại cho mỗi dòng. Ví dụ, nghiên cứu và phân tích cú pháp sẽ được vận dụng cho mỗi dòng độc lập với những dòng khác, và do đó trình thông dịch mất rất nhiều thời hạn để dịch mã. Trình biên dịch xử lý yếu tố này vì nó hoàn toàn có thể giải quyết và xử lý toàn bộ mã cùng một lúc và do đó nghiên cứu và phân tích cú pháp sẽ chỉ được vận dụng một lần thay vì cho từng dòng mã. Do đó, mã bytecode được tạo ra từ trình biên dịch sẽ được diễn giải thuận tiện. Lưu ý rằng việc biên dịch hàng loạt mã nguồn hoàn toàn có thể không có ích trong 1 số ít trường hợp và tất cả chúng ta sẽ thấy một ví dụ rõ ràng về điều này khi tranh luận về PyPy .
Sau khi mã bytecode được tạo, nó được thực thi bởi trình thông dịch chạy trong máy ảo. Môi trường ảo có lợi, vì nó cách ly bytecode CPython khỏi máy và do đó làm cho Python đa nền tảng .
Thật không may, chỉ sử dụng một trình biên dịch để tạo bytecode là không đủ để tăng tốc độ thực thi CPython. Trình thông dịch hoạt động bằng cách dịch mã, mỗi khi nó được thực thi, thành mã máy. Do đó, nếu một dòng L
mất X
vài giây để được thực thi, thì việc thực thi nó 10 lần sẽ có chi phí là X*10
giây. Đối với các hoạt động kéo dài, điều này quá tốn kém về thời gian thực hiện.
Dựa trên những điểm hạn chế của CPython, giờ đây tất cả chúng ta hãy cùng PyPy xem qua .
Giới thiệu về PyPy và các tính năng của nó
PyPy là một tiến hành Python tương tự như như CPython vừa tuân thủ vừa nhanh gọn. “ Tuân thủ ” có nghĩa là PyPy thích hợp với CPython, vì bạn hoàn toàn có thể sử dụng gần như toàn bộ những cú pháp CPython trong PyPy. Có 1 số ít độc lạ về năng lực thích hợp, như đã đề cập ở đây. Ưu điểm mạnh nhất của PyPy là vận tốc. PyPy nhanh hơn nhiều so với CPython ; tất cả chúng ta sẽ xem những thử nghiệm sau đó về việc PyPy thực thi nhanh hơn khoảng chừng 7 lần. Trong 1 số ít trường hợp, nó thậm chí còn hoàn toàn có thể nhanh hơn CPython hàng chục hoặc hàng trăm lần. Vậy làm cách nào để PyPy đạt được vận tốc ?
Tốc độ
PyPy sử dụng trình biên dịch đúng lúc ( JIT ) hoàn toàn có thể tăng đáng kể vận tốc của những tập lệnh Python. Loại biên dịch được sử dụng trong CPython là trước thời hạn ( AOT ), có nghĩa là tổng thể mã sẽ được dịch thành bytecode trước khi được thực thi. JIT chỉ dịch mã trong thời hạn chạy, chỉ khi nó thiết yếu .
Mã nguồn hoàn toàn có thể chứa những khối mã trọn vẹn không được thực thi, nhưng chúng vẫn đang được dịch bằng trình biên dịch AOT. Điều này dẫn đến thời hạn giải quyết và xử lý chậm hơn. Khi mã nguồn lớn và chứa hàng nghìn dòng, việc sử dụng JIT tạo ra sự độc lạ lớn. Đối với AOT, hàng loạt mã nguồn sẽ được dịch và do đó mất rất nhiều thời hạn. Đối với JIT, chỉ những phần thiết yếu của mã sẽ được thực thi, làm cho nó nhanh hơn rất nhiều .
Sau khi PyPy dịch một phần của mã, nó sẽ được lưu vào bộ nhớ đệm. Điều này có nghĩa là mã chỉ được dịch một lần và sau đó bản dịch sẽ được sử dụng sau đó. Trình thông dịch CPython lặp lại bản dịch mỗi khi mã được thực thi, một nguyên do bổ trợ cho sự lờ đờ của nó .
Nỗ lực
PyPy không phải là cách duy nhất để tăng hiệu suất của những tập lệnh Python – nhưng nó là cách dễ nhất. Ví dụ, Cython hoàn toàn có thể được sử dụng để tăng vận tốc gán kiểu C cho những biến. Vấn đề là Cython nhu yếu nhà tăng trưởng tự kiểm tra mã nguồn và tối ưu hóa nó. Điều này thật căng thẳng mệt mỏi và độ phức tạp tăng lên khi kích cỡ mã tăng lên. Khi PyPy được sử dụng, bạn chỉ cần chạy mã Python thường thì nhanh hơn nhiều mà không cần nỗ lực gì cả .
Xếp chồng lên nhau
Python chuẩn sử dụng ngăn xếp C. Ngăn xếp này tàng trữ chuỗi những hàm được gọi từ nhau ( đệ quy ). Bởi vì kích cỡ ngăn xếp có số lượng giới hạn, bạn bị số lượng giới hạn số lần gọi hàm .
PyPy sử dụng Stackless Python, một thực hiện Python rằng không sử dụng C ngăn xếp. Thay vào đó, nó lưu trữ các lệnh gọi hàm trong đống cùng với các đối tượng. Kích thước heap lớn hơn kích thước ngăn xếp và do đó bạn có thể thực hiện nhiều lệnh gọi hàm hơn.
Stackless Python cũng tương hỗ những vi luồng, tốt hơn những luồng Python thường thì. Trong chuỗi Stackless Python duy nhất, bạn hoàn toàn có thể chạy hàng nghìn tác vụ, được gọi là “ tasklet ”, với toàn bộ chúng đều chạy trên cùng một chuỗi .
Sử dụng tasklet được cho phép chạy những tác vụ đồng thời. Đồng thời có nghĩa là hai tác vụ hoạt động giải trí đồng thời bằng cách san sẻ cùng một tài nguyên. Một tác vụ chạy trong một khoảng chừng thời hạn, sau đó dừng lại để nhường chỗ cho tác vụ thứ hai được thực thi. Lưu ý rằng điều này khác với song song, gồm có việc chạy hai tác vụ riêng không liên quan gì đến nhau nhưng cùng một lúc .
Việc sử dụng những tasklet làm giảm số lượng những luồng được tạo ra và do đó giảm ngân sách quản trị tổng thể những luồng này bởi Hệ quản lý. Do đó, việc tăng vận tốc thực thi bằng cách hoán đổi giữa hai luồng sẽ tốn nhiều thời hạn hơn so với việc hoán đổi giữa hai tasklet .
Sử dụng Stackless Python cũng mở ra cánh cửa cho việc tiến hành những phép liên tục. Việc liên tục được cho phép chúng tôi lưu trạng thái của một tác vụ và Phục hồi nó sau đó để liên tục việc làm của nó. Lưu ý rằng Stackless Python không khác với Python chuẩn ; nó chỉ thêm nhiều tính năng hơn. Mọi thứ có sẵn trong Python chuẩn cũng sẽ có sẵn trong Stackless Python .
Sau khi luận bàn về những quyền lợi của PyPy, tất cả chúng ta hãy nói về những hạn chế của nó trong phần tiếp theo .
Hạn chế của PyPy
Mặc dù bạn có thể sử dụng CPython trên bất kỳ máy nào và bất kỳ kiến trúc CPU nào, PyPy có hỗ trợ tương đối hạn chế.
Dưới đây là những kiến trúc CPU được tương hỗ và duy trì bởi PyPy ( nguồn ) :
- x86 (IA-32) và x86_64
- Nền tảng ARM (ARMv6 hoặc ARMv7, với VFPv3)
- AArch64
- PowerPC 64bit, cả endian nhỏ và lớn
- Hệ thống Z (s390x)
Nếu mã được thực thi trong PyPy là Python thuần túy, thì vận tốc do PyPy cung ứng thường đáng quan tâm. Nhưng nếu mã chứa phần lan rộng ra C, ví dụ điển hình như NumPy, thì PyPy thực sự hoàn toàn có thể tăng thời hạn. Dự án PyPy đang được tăng trưởng tích cực và do đó hoàn toàn có thể tương hỗ tốt hơn cho những phần lan rộng ra C trong tương lai .
PyPy không được tương hỗ bởi 1 số ít khuôn khổ Python thông dụng, ví dụ điển hình như Kivy. Kivy được cho phép CPython chạy trên mọi nền tảng, gồm có cả Android và iOS. Điều này có nghĩa là PyPy không hề chạy trên thiết bị di động .
Bây giờ tất cả chúng ta đã thấy những quyền lợi và hạn chế của PyPy, tất cả chúng ta hãy xem cách chạy PyPy trên Ubuntu .
Chạy PyPy trên Ubuntu
Bạn hoàn toàn có thể chạy PyPy trên Mac, Linux hoặc Windows, nhưng tất cả chúng ta sẽ đàm đạo về việc chạy nó trên Ubuntu. Điều rất quan trọng cần đề cập lại là những tệp nhị phân PyPy Linux chỉ được tương hỗ trên những bản phân phối Linux đơn cử. Bạn hoàn toàn có thể kiểm tra những tệp nhị phân PyPy có sẵn và những bản phân phối được tương hỗ của chúng trên trang này. Ví dụ : PyPy ( Python 2.7 hoặc Python 3.6 ) chỉ được tương hỗ cho ba phiên bản Ubuntu : 18.04, 16.04 và 14.04. Nếu bạn có phiên bản Ubuntu mới nhất cho đến ngày này ( 19.10 ), thì bạn không hề chạy PyPy trên đó. Cố gắng chạy PyPy trên bản phân phối không được tương hỗ sẽ trả về lỗi này :
pypy: error while loading shared libraries ...
Tôi chỉ đơn thuần là sử dụng một máy ảo để chạy Ubuntu 18.04 .
Các tệp nhị phân PyPy có dạng tệp nén. Tất cả những gì bạn cần làm là giải nén tệp bạn đã tải xuống. Bên trong thư mục được giải nén có một thư mục được đặt tên bin
, trong đó có thể tìm thấy tệp thực thi PyPy. Tôi đang sử dụng Python 3.6 và do đó tệp được đặt tên pypy3
. Đối với Python 2.7, nó chỉ được gọi pypy
.
Đối với CPython, nếu bạn muốn chạy Python 3 từ thiết bị đầu cuối, bạn chỉ cần nhập lệnh python3
. Để chạy PyPy, chỉ cần đưa ra lệnh pypy3
.
Nhập pypy3
lệnh trong thiết bị đầu cuối có thể trả về Command 'pypy3' not found
thông báo, như thể hiện trong hình tiếp theo. Lý do là đường dẫn của PyPy không được thêm vào biến môi trường PATH. Lệnh thực sự hoạt động là ./pypy3
, lưu ý rằng đường dẫn hiện tại của thiết bị đầu cuối nằm trong bin
thư mục của PyPy. Dấu chấm .
đề cập đến thư mục hiện tại và /
được thêm vào để truy cập một thứ gì đó trong thư mục hiện tại. Phát ./pypy3
lệnh chạy Python thành công như được đưa ra bên dưới.
Bây giờ bạn hoàn toàn có thể thao tác với Python như thông thường, tận dụng những quyền lợi của PyPy. Ví dụ : tất cả chúng ta hoàn toàn có thể tạo một tập lệnh Python đơn thuần tính tổng 1.000 số và thực thi nó bằng PyPy. Mã như sau .
nums = range(1000)
sum = 0
for k in nums:
sum = sum + k
print("Sum of 1,000 numbers is : ", sum)
./pypy3 test.py
Thời gian thực hiện của PyPy so với CPython
Để so sánh thời hạn chạy của PyPy và CPython để tính tổng 1.000 số, mã được đổi khác để đo thời hạn như sau .
import time
t1 = time.time()
nums = range(1000)
sum = 0
for k in nums:
sum = sum + k
print("Sum of 1,000 numbers is : ", sum)
t2 = time.time()
t = t2 - t1
print("Elapsed time is : ", t, " seconds")
Bài viết này ban đầu được xuất bản trên blog Paperspace. Bạn có thể chạy mã cho các hướng dẫn của tôi miễn phí trên Gradient .
Phần kết luận
Hướng dẫn này đã trình làng PyPy, cách tiến hành Python nhanh nhất. Lợi ích chính của PyPy là biên dịch đúng lúc ( JIT ), cung ứng bộ nhớ đệm mã máy đã biên dịch để tránh thực thi lại. Những hạn chế của PyPy cũng được nhấn mạnh vấn đề, một trong những hạn chế chính là nó hoạt động giải trí tốt với mã Python thuần túy nhưng không hiệu suất cao so với những phần lan rộng ra C .
Chúng tôi cũng đã xem cách chạy PyPy trên Ubuntu và so sánh thời hạn chạy của cả CPython và PyPy, làm điển hình nổi bật hiệu suất cao của PyPy so với những tác vụ chạy lâu. Trong khi đó, CPython vẫn hoàn toàn có thể vượt mặt PyPy so với những tác vụ chạy ngắn. Trong những bài viết tiếp theo, chúng tôi sẽ tò mò thêm những so sánh giữa PyPy, CPython và Cython .