PyPy - Làm thế nào nó có thể đánh bại CPython?


264

Từ Blog nguồn mở của Google :

PyPy là sự tái hiện của Python trong Python, sử dụng các kỹ thuật nâng cao để cố gắng đạt được hiệu suất tốt hơn CPython. Nhiều năm làm việc chăm chỉ cuối cùng cũng được đền đáp. Kết quả tốc độ của chúng tôi thường đánh bại CPython, từ chậm hơn một chút, tăng tốc lên tới 2 lần trên mã ứng dụng thực, đến tăng tốc lên tới 10 lần trên các điểm chuẩn nhỏ.

Sao có thể như thế được? Việc triển khai Python nào đã được sử dụng để triển khai PyPy? CPython ? Và cơ hội của một PyPyPy hoặc PyPyPyPy đánh bại điểm số của họ là gì?

(Trên một ghi chú liên quan ... tại sao mọi người sẽ thử một cái gì đó như thế này?)


43
Nitpick: PyPy PyPyPy. Hãy nghĩ về tiền tố Py- * như một toán tử chiếu.
u0b34a0f6ae

Đồng ý. vậy PyPy nên được ưu tiên hơn CPython? nó có bất kỳ nhược điểm nào không?
balki

10
PyPy rất tuyệt vời trong việc tối ưu hóa thời gian chạy, nhưng các bộ phận khác nhau của nó làm cho nó không tương thích với một số phần mở rộng C phổ biến.
Cees Timmerman

4
Hầu như tất cả mọi người đang bỏ lỡ câu hỏi, như làm thế nào để tăng tốc độ là LÝ THUYẾT có thể. Nhưng hãy nghĩ về nó: Python có thể làm bất cứ điều gì, giống như một máy Turing. Nó có thể gọi gcc, sau tất cả. Vì vậy, bạn cũng có thể viết một số mã python chạy trên CPython, thông dịch một số mã python khác, dịch nó sang C và thực thi gcc, sau đó thực thi chương trình đã biên dịch. Và nó có thể nhanh hơn, nếu mã được gọi thường xuyên đủ.
osa

Câu trả lời:


155

Q1. Sao có thể như thế được?

Quản lý bộ nhớ thủ công (đó là những gì CPython làm với việc đếm) có thể chậm hơn quản lý tự động trong một số trường hợp.

Những hạn chế trong việc triển khai trình thông dịch CPython loại trừ những tối ưu nhất định mà PyPy có thể làm (ví dụ: khóa hạt mịn).

Như Marcelo đã đề cập, JIT. Việc có thể nhanh chóng xác nhận loại đối tượng có thể giúp bạn tiết kiệm nhu cầu thực hiện nhiều cuộc hội thảo con trỏ để cuối cùng đến phương thức bạn muốn gọi.

Quý 2 Việc triển khai Python nào đã được sử dụng để triển khai PyPy?

Trình thông dịch PyPy được triển khai trong RPython, đây là một tập hợp con được gõ tĩnh của Python (ngôn ngữ chứ không phải trình thông dịch CPython). - Tham khảo https://pypy.readthedocs.org/en/latest/arch architecture.html để biết chi tiết.

H3 Và cơ hội của một PyPyPy hoặc PyPyPyPy đánh bại điểm số của họ là gì?

Điều đó sẽ phụ thuộc vào việc thực hiện các thông dịch viên giả định này. Ví dụ, nếu một trong số họ lấy nguồn, đã thực hiện một số phân tích về nó và chuyển đổi trực tiếp thành mã lắp ráp cụ thể mục tiêu chặt chẽ sau khi chạy một lúc, tôi tưởng tượng nó sẽ khá nhanh hơn CPython.

Cập nhật: Gần đây, trên một ví dụ được chế tạo cẩn thận , PyPy đã vượt trội so với một chương trình C tương tự được biên dịch cùng gcc -O3. Đó là một trường hợp giả định nhưng thể hiện một số ý tưởng.

Q4. Tại sao mọi người sẽ thử một cái gì đó như thế này?

Từ trang web chính thức. https://pypy.readthedocs.org/en/latest/arch architecture.html #mission-stement

Chúng tôi mong muốn cung cấp:

  • một khung dịch và hỗ trợ chung để tạo ra các
    triển khai ngôn ngữ động, nhấn mạnh sự
    tách biệt rõ ràng giữa các đặc điểm ngôn ngữ và
    các khía cạnh triển khai . Chúng tôi gọi đây là RPython toolchain_.

  • việc triển khai nhanh chóng, linh hoạt và nhanh chóng của Ngôn ngữ Python_ sử dụng chuỗi công cụ trên để kích hoạt các tính năng cấp cao nâng cao mới mà không phải mã hóa các chi tiết cấp thấp.

Bằng cách tách các mối quan tâm theo cách này, việc triển khai Python của chúng tôi - và các ngôn ngữ động khác - có thể tự động tạo trình biên dịch Just-in-Time cho bất kỳ ngôn ngữ động nào. Nó cũng cho phép một cách tiếp cận hỗn hợp và phù hợp với các quyết định triển khai, bao gồm nhiều quyết định nằm ngoài sự kiểm soát của người dùng, chẳng hạn như nền tảng đích, mô hình bộ nhớ và luồng, chiến lược thu gom rác và tối ưu hóa được áp dụng, bao gồm cả việc có hay không một JIT ở nơi đầu tiên.

Trình biên dịch C gcc được triển khai trong C, Trình biên dịch Haskell GHC được viết bằng Haskell. Bạn có bất kỳ lý do nào để trình thông dịch / trình biên dịch Python không được viết bằng Python không?


82
Câu trả lời này hoàn toàn thiếu lời giải thích chính cho việc PyPy nhanh như thế nào; Mặc dù đề cập rằng PyPy không thực sự được triển khai trong Python, nhưng trong RPython, nó không chỉ ra rằng mã RPython được biên dịch tĩnh và tối ưu hóa để tạo trình thông dịch PyPy (nó cũng chỉ là mã Python hợp lệ có thể chạy trên đầu trang của CPython chậm hơn nhiều). Những gì họ đã thực hiện trong "Python bình thường" là "trình biên dịch" RPython (khung dịch được đề cập trong trích dẫn khối).
Ben

12
Đây là chôn vùi lede. Hầu hết các hiệu suất đến từ dịch sang C (làm cho trình thông dịch không chậm hơn CPython) và JIT, làm cho các đường dẫn nóng nhanh hơn nhiều.
Tobu

4
"Cập nhật: Gần đây, trên một ví dụ được chế tạo cẩn thận, PyPy đã vượt trội so với một chương trình C tương tự được biên dịch với gcc -O3." Và nếu bạn đọc bình luận đầu tiên dưới bài đăng đó, bạn sẽ thấy rằng người viết bài đăng đó không biết tối ưu hóa thời gian liên kết. Khi tối ưu hóa thời gian liên kết được bật, mã C chạy nhanh hơn.
Ali

2
Vâng, bài viết trên blog là vào năm 2011 và câu trả lời này vào năm 2014. Ngoài ra, bình luận có đề cập đến các thư viện chia sẻ. Tôi không biết bao nhiêu trong số này (câu trả lời và bài đăng trên blog) là hợp lệ. Tất cả các công nghệ liên quan đã thay đổi rất nhiều trong vài năm qua.
Noufal Ibrahim

1
Trên hai ví dụ được chế tạo cẩn thận về Pypy nhanh hơn C tương đương, mỗi ví dụ nhanh hơn về điểm chuẩn vì một lý do rất cụ thể. Thứ nhất bởi vì Pypy đủ thông minh để nhận ra các vòng đếm chặt chẽ không bao giờ sử dụng số đếm đó, do đó, nó có thể bị xóa hoàn toàn (vượt qua JIT) lần thứ hai cho sự kết hợp của: bởi vì Pypy JIT có thể "nội tuyến qua ranh giới thư viện", được đưa ra ví dụ về chức năng "printf" được chuyên biệt hóa theo nghĩa đen chỉ có thể phát ra một số nguyên và loại bỏ malloc lặp lại (phí phân bổ bộ nhớ).
amcgregor

291

"PyPy là sự tái hiện của Python trong Python" là một cách khá sai lầm để mô tả PyPy, IMHO, mặc dù về mặt kỹ thuật là đúng.

Có hai phần chính của PyPy.

  1. Khung dịch thuật
  2. Thông dịch viên

Khung dịch là một trình biên dịch. Nó biên dịch mã RPython xuống C (hoặc các mục tiêu khác), tự động thêm vào các khía cạnh như bộ sưu tập rác và trình biên dịch JIT. Nó không thể xử lý mã Python tùy ý, chỉ RPython.

RPython là một tập hợp con của Python bình thường; tất cả mã RPython là mã Python, nhưng không phải là cách khác. Không có định nghĩa chính thức về RPython, vì về cơ bản RPython chỉ là "tập hợp con của Python có thể được dịch theo khung dịch của PyPy". Nhưng để được dịch, mã RPython phải được nhập tĩnh (các loại được suy ra, bạn không khai báo chúng, nhưng nó vẫn đúng một loại cho mỗi biến) và bạn không thể thực hiện những việc như khai báo / sửa đổi hàm / các lớp trong thời gian chạy hoặc.

Trình thông dịch sau đó là một trình thông dịch Python bình thường được viết bằng RPython.

Vì mã RPython là mã Python bình thường, bạn có thể chạy nó trên bất kỳ trình thông dịch Python nào. Nhưng không có tuyên bố tốc độ nào của PyPy đến từ việc chạy theo cách đó; đây chỉ là một chu kỳ kiểm tra nhanh, bởi vì việc dịch trình thông dịch mất nhiều thời gian.

Với sự hiểu biết đó, rõ ràng ngay lập tức rằng những suy đoán về PyPyPy hoặc PyPyPyPy thực sự không có ý nghĩa gì. Bạn có một thông dịch viên viết bằng RPython. Bạn dịch nó sang mã C thực thi Python nhanh chóng. Có quá trình dừng lại; không còn RPython để tăng tốc bằng cách xử lý lại.

Vì vậy, "Làm thế nào để PyPy có thể nhanh hơn CPython" cũng trở nên khá rõ ràng. PyPy có triển khai tốt hơn, bao gồm trình biên dịch JIT (nói chung nó không hoàn toàn nhanh như không có trình biên dịch JIT, điều đó có nghĩa là PyPy chỉ nhanh hơn đối với các chương trình dễ bị biên dịch JIT). CPython không bao giờ được thiết kế để trở thành một triển khai tối ưu hóa ngôn ngữ Python (mặc dù họ cố gắng biến nó thành một triển khai được tối ưu hóa cao , nếu bạn tuân theo sự khác biệt).


Điểm thực sự sáng tạo của dự án PyPy là họ không viết các lược đồ GC hoặc trình biên dịch JIT tinh vi bằng tay. Họ viết trình thông dịch tương đối đơn giản bằng RPython và với tất cả RPython ở mức thấp hơn Python, nó vẫn là ngôn ngữ thu thập rác hướng đối tượng, mức cao hơn nhiều so với C. Sau đó, khung dịch thuật sẽ tự động thêm các thứ như GC và JIT. Vì vậy, khung dịch thuật là rất lớnnỗ lực, nhưng nó cũng áp dụng tốt cho trình thông dịch python PyPy tuy nhiên họ thay đổi cách thực hiện, cho phép thử nghiệm nhiều hơn để cải thiện hiệu suất (mà không phải lo lắng về việc giới thiệu các lỗi của GC hoặc cập nhật trình biên dịch JIT để đối phó với các thay đổi). Điều đó cũng có nghĩa là khi họ bắt đầu triển khai trình thông dịch Python3, nó sẽ tự động nhận được các lợi ích tương tự. Và bất kỳ thông dịch viên nào khác được viết với khung PyPy (trong đó có một số ở các giai đoạn đánh bóng khác nhau). Và tất cả các thông dịch viên sử dụng khung PyPy sẽ tự động hỗ trợ tất cả các nền tảng được khung hỗ trợ.

Vì vậy, lợi ích thực sự của dự án PyPy là tách biệt (càng nhiều càng tốt) tất cả các phần của việc thực hiện một trình thông dịch độc lập với nền tảng hiệu quả cho một ngôn ngữ động. Và sau đó đưa ra một triển khai tốt của chúng ở một nơi, có thể được sử dụng lại trên nhiều phiên dịch viên. Đó không phải là một chiến thắng ngay lập tức như "chương trình Python của tôi chạy nhanh hơn bây giờ", nhưng đó là một triển vọng lớn cho tương lai.

Và nó có thể chạy chương trình Python của bạn nhanh hơn (có thể).


4
Tôi không thể làm theo sự khác biệt :(
polvoazul

37
@polvoazul Sự khác biệt giữa một tối ưu hóa thực hiện ngôn ngữ và tối ưu hóa một? Vâng, khi tôi nói CPython là một triển khai được tối ưu hóa tốt, tôi có nghĩa là các nhà phát triển cố gắng làm cho các thuật toán bên trong của chính trình thông dịch và các cấu trúc dữ liệu dựng sẵn chạy hiệu quả. Việc triển khai tối ưu hóa , OTOH, sẽ phân tích mã người dùng cuối và cố gắng tìm ra các cách để chuyển đổi nó để thực thi hiệu quả hơn.
Bến

23

PyPy được triển khai trong Python, nhưng nó thực hiện trình biên dịch JIT để tạo mã gốc khi đang di chuyển.

Lý do để triển khai PyPy trên Python có lẽ đơn giản là nó là một ngôn ngữ rất hiệu quả, đặc biệt là vì trình biên dịch JIT làm cho hiệu suất của ngôn ngữ máy chủ có phần không liên quan.


JIT có tạo mã Python chạy cùng cấp với PyPy không, hay nó tạo mã gốc thực sự chạy ở cấp độ nào mà triển khai Python mà PyPy đang chạy?
Edmund

3
Mã gốc thực sự (xem tại đây ); Chính xác là mã x86 32 bit.
Marcelo Cantos

11

PyPy được viết bằng Python bị hạn chế. Nó không chạy trên trình thông dịch CPython, theo như tôi biết. Python bị hạn chế là một tập hợp con của ngôn ngữ Python. AFAIK, trình thông dịch PyPy được biên dịch thành mã máy, vì vậy khi cài đặt, nó không sử dụng trình thông dịch python khi chạy.

Câu hỏi của bạn dường như mong đợi trình thông dịch PyPy đang chạy trên CPython trong khi thực thi mã. Chỉnh sửa: Có, để sử dụng PyPy, trước tiên bạn dịch mã python PyPy, sang C và xây dựng bằng gcc, sang mã byte jvm hoặc mã .Net CLI. Xem Bắt đầu


8
PyPy sẽ chạy trên CPython nhưng trong chế độ này, nó không cung cấp tốc độ tăng mà người ta có thể mong muốn. :-) Codepeak.net/pypy/dist/pypy/doc/ từ
Frank V
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.