Những tính năng ngữ nghĩa nào của Python (và các ngôn ngữ động khác) góp phần vào sự chậm chạp của nó?


26

Tôi không biết nhiều về Python. Tôi đang cố gắng để hiểu chính xác hơn các tính năng chính xác của các ngôn ngữ động (à la Python, Lua, Scheme, Perl, Ruby, ....) đang buộc việc triển khai của chúng bị chậm.

Như một trường hợp cụ thể, máy móc có thể thay đổi Lua 5.3 sẽ trực giác làm cho Lua khá chậm, nhưng trong thực tế, Lua được đồn đại là khá nhanh (và nhanh hơn Python).

Ngoài ra, tôi có một trực giác (có lẽ là sai) vì bộ nhớ của bộ xử lý hiện tại chậm hơn nhiều so với tính toán thô (truy cập bộ nhớ với bộ nhớ cache cần cùng lúc với hàng trăm thao tác số học), kiểm tra kiểu động (à la if (value->type != INTEGER_TAG) return;in C parlance) có thể chạy khá nhanh.

Tất nhiên, toàn bộ phân tích chương trình (như triển khai Đề án Stalin đang thực hiện) có thể khiến việc triển khai ngôn ngữ động trở thành một dịch giả chạy nhanh, nhưng trước tiên hãy giả vờ rằng tôi không có thời gian để thiết kế một bộ phân tích chương trình.

(Tôi sắp xếp một ngôn ngữ động trong màn hình MELT của mình và một số ngôn ngữ sẽ được dịch sang C)



1
Lua Performance Tips , giải thích tại sao một số chương trình Lua bị chậm và cách khắc phục chúng.
Robert Harvey

Câu trả lời:


24

Những tính năng ngữ nghĩa nào của Python (và các ngôn ngữ động khác) góp phần vào sự chậm chạp của nó?

Không ai.

Hiệu suất của việc thực hiện ngôn ngữ là một chức năng của tiền, tài nguyên và luận án tiến sĩ, không phải là tính năng ngôn ngữ. Bản thân năng động hơn nhiều so với Smalltalk và năng động hơn một chút so với Python, Ruby, ECMAScript hoặc Lua và nó có một VM vượt trội hơn tất cả các VM Lisp và Smalltalk hiện có (trên thực tế, bản phân phối Self được vận chuyển với một trình thông dịch Smalltalk nhỏ được viết bằng Self và thậm chí còn nhanh hơn hầu hết các máy ảo Smalltalk hiện tại) và có khả năng cạnh tranh, và đôi khi còn nhanh hơn cả các triển khai C ++ thời đó.

Sau đó, Sun ngừng tài trợ cho Self và IBM, Microsoft, Intel và Co. bắt đầu tài trợ cho C ++ và xu hướng đã đảo ngược. Các nhà phát triển Self đã rời Sun để thành lập công ty riêng của họ, nơi họ đã sử dụng công nghệ được phát triển cho Self VM để xây dựng một trong những máy ảo Smalltalk nhanh nhất từng có (VM hoạt hình), và sau đó Sun đã mua lại công ty đó và một phiên bản sửa đổi một chút rằng Smalltalk VM hiện được biết đến nhiều hơn dưới cái tên "HotSpot JVM". Trớ trêu thay, các lập trình viên Java lại coi các ngôn ngữ động là "chậm", trong khi thực tế, Javađã chậm cho đến khi nó áp dụng công nghệ ngôn ngữ năng động. (Vâng, đúng vậy: HotSpot JVM về cơ bản là một máy ảo Smalltalk. Trình xác minh mã byte thực hiện nhiều kiểm tra kiểu, nhưng một khi mã byte được chấp nhận bởi trình xác minh, VM và đặc biệt là trình tối ưu hóa và JIT không thực sự làm nhiều quan tâm với các loại tĩnh!)

CPython đơn giản là không thực hiện được nhiều thứ giúp ngôn ngữ động (hay thay vì gửi động) nhanh chóng: biên dịch động (JIT), tối ưu hóa động, nội tuyến đầu cơ, tối ưu hóa thích ứng, tối ưu hóa động, phản hồi / suy luận kiểu động. Ngoài ra còn có một vấn đề là gần như toàn bộ thư viện lõi và thư viện chuẩn được viết bằng C, điều đó có nghĩa là ngay cả khi bạn tạo Python nhanh hơn 100 lần một cách đột ngột, nó sẽ không giúp bạn nhiều, bởi vì có gì đó giống như 95% mã được thực thi bởi Chương trình Python là C, không phải Python. Nếu mọi thứ được viết bằng Python, ngay cả việc tăng tốc độ vừa phải cũng sẽ tạo ra hiệu ứng, trong đó các thuật toán nhanh hơn và các cơ sở dữ liệu cốt lõi nhanh hơn, nhưng tất nhiên các cấu trúc dữ liệu cốt lõi cũng được sử dụng trong các thuật toán và thuật toán lõi và dữ liệu cốt lõi cấu trúc được sử dụng ở mọi nơi khác,

Có một vài điều nổi tiếng là xấu đối với các ngôn ngữ OO được quản lý bộ nhớ (động hoặc không) trong các hệ thống ngày nay. Bộ nhớ ảo và Bảo vệ bộ nhớ có thể là một kẻ giết người đối với hiệu suất thu gom rác nói riêng và hiệu năng hệ thống nói chung. Và nó hoàn toàn không cần thiết trong ngôn ngữ an toàn bộ nhớ: tại sao phải bảo vệ chống lại truy cập bộ nhớ bất hợp pháp khi không có bất kỳ truy cập bộ nhớ nào trong ngôn ngữ để bắt đầu? Azul đã tìm ra cách sử dụng các MMU mạnh mẽ hiện đại (Intel Nehalem và mới hơn và tương đương AMD) để giúp thu gom rác thay vì cản trở nó, nhưng mặc dù được CPU hỗ trợ, các hệ thống con bộ nhớ hiện tại của HĐH chính thống không đủ mạnh để cho phép điều này (đó là lý do tại sao JVM của Azul thực sự chạy ảo hóa trên kim loại trần bên cạnh HĐH, không nằm trong nó).

Trong dự án HĐH Singularity, Microsoft đã đo lường tác động ~ 30% đến hiệu suất hệ thống khi sử dụng bảo vệ MMU thay vì hệ thống loại để phân tách quy trình.

Một điều khác mà Azul nhận thấy khi xây dựng các CPU Java chuyên dụng của họ là các CPU chính hiện đại tập trung vào điều hoàn toàn sai khi cố gắng giảm chi phí của bộ nhớ cache: họ cố gắng giảm số lượng bộ nhớ cache thông qua những thứ như dự đoán nhánh, tìm nạp trước bộ nhớ, vân vân Nhưng, trong một chương trình OO đa hình nặng, các mẫu truy cập về cơ bản là giả ngẫu nhiên, đơn giản là không có gì để dự đoán. Vì vậy, tất cả các bóng bán dẫn đó chỉ bị lãng phí, và điều người ta nên làm thay vào đó là giảm chi phí cho mỗi bộ nhớ cache riêng lẻ. (Tổng chi phí là #misses * chi phí, dòng chính cố gắng hạ xuống thứ nhất, Azul thứ hai.) Bộ gia tốc tính toán Java của Azul có thể có 20000 lỗi bộ nhớ cache đồng thời trong chuyến bay và vẫn đạt được tiến bộ.

Khi Azul bắt đầu, họ nghĩ rằng họ sẽ lấy một số thành phần I / O ngoài luồng và thiết kế lõi CPU chuyên dụng của riêng họ, nhưng những gì họ thực sự cần phải làm lại hoàn toàn ngược lại: họ đã lấy một thứ khá tiêu chuẩn kệ lõi RISC 3 địa chỉ và thiết kế bộ điều khiển bộ nhớ, MMU và hệ thống con bộ đệm của riêng họ.

tl; dr : "sự chậm chạp" của Python không phải là một đặc tính của ngôn ngữ mà là một) triển khai (chính) ngây thơ của nó và b) thực tế là các CPU và HĐH hiện đại được thiết kế đặc biệt để làm cho C chạy nhanh và các tính năng của chúng có cho C là không giúp đỡ (bộ nhớ cache) hoặc thậm chí tích cực làm tổn thương (bộ nhớ ảo) hiệu suất Python.

Và bạn có thể chèn khá nhiều ngôn ngữ được quản lý bộ nhớ với tính đa hình ad-hoc động ở đây khi nói đến những thách thức của việc triển khai hiệu quả, ngay cả Python và Java cũng có "cùng một ngôn ngữ".


Bạn có một liên kết hoặc tài liệu tham khảo cho Azul?
Basile Starynkevitch

4
Tôi không đồng ý rằng ngữ nghĩa của một ngôn ngữ không ảnh hưởng đến khả năng thực thi hiệu quả của nó. Vâng, một JIT thực hiện tốt với tối ưu hạng nhất và phân tích có thể làm cho một lớn cải thiện đến việc thực hiện một ngôn ngữ, nhưng cuối cùng có một số khía cạnh của ngữ nghĩa rằng không thể tránh khỏi sẽ kết thúc được tắc nghẽn. Cho dù đó là yêu cầu của C đối với việc khử răng cưa nghiêm ngặt hay yêu cầu của Python rằng các hoạt động liệt kê được thực hiện nguyên tử, vẫn có những quyết định ngữ nghĩa nhất định không thể tránh khỏi làm ảnh hưởng đến hiệu suất của một số ứng dụng.
Jules

1
Là một bên ... bạn có tham khảo cho cải thiện 30% cho Singularity không? Tôi đã từng là người ủng hộ các hệ điều hành bảo vệ dựa trên ngôn ngữ trong nhiều năm, nhưng chưa bao giờ thấy con số đó trước đây và thấy nó khá giật mình (những con số tôi đã nhìn thấy trong quá khứ đã gần 10%) và tự hỏi điều gì họ đã làm để có được sự cải thiện đó ...
Jules

5
@MasonWheeler: Bởi vì chỉ có những triển khai Python nhảm nhí ngoài kia. Không có người triển khai Python nào đã chi thậm chí một phần rất nhỏ tiền, con người, nghiên cứu và tài nguyên mà IBM, Sun, Oracle, Google và Co. đã chi cho J9, JRockit, HotSpot và Co. Cả 5 triển khai Python có thể thậm chí không có nhân lực mà Oracle đang chi cho người thu gom rác. IBM đang làm việc trên một triển khai Python dựa trên OMR Eclipse (khung VM có nguồn mở được thành phần được trích xuất từ ​​J9), tôi sẵn sàng đặt cược rằng hiệu suất của nó sẽ tốt trong một mức độ lớn của J9
Jörg W Mittag

2
Đối với bản ghi C chậm so với Fortran đối với công việc số vì Fortran thi hành bí danh nghiêm ngặt để trình tối ưu hóa có thể mạnh hơn.
Michael Storesin

8

Mặc dù triển khai hiện tại của Python (thiếu rất nhiều tối ưu hóa được thực hiện bởi các ngôn ngữ động khác, ví dụ như triển khai Javascript hiện đại và, như bạn chỉ ra, Lua) là một nguồn gốc của hầu hết các vấn đề của nó, nó có một số vấn đề ngữ nghĩa sẽ làm cho nó khó thực hiện để cạnh tranh với các ngôn ngữ khác, ít nhất là trong các lĩnh vực nhất định. Một số đáng để xem xét đặc biệt:

  • Các hoạt động danh sách và từ điển được yêu cầu bởi định nghĩa ngôn ngữ là nguyên tử. Điều này có nghĩa là trừ khi trình biên dịch JIT có thể chứng minh rằng không có tham chiếu nào đến đối tượng danh sách đã thoát khỏi luồng hiện tại của nó (một phân tích khó trong nhiều trường hợp và không thể trong trường hợp chung), nó phải đảm bảo quyền truy cập vào đối tượng được tuần tự hóa (ví dụ thông qua khóa). Việc triển khai CPython giải quyết vấn đề này bằng cách sử dụng "khóa trình thông dịch toàn cầu" khét tiếng để ngăn chặn mã Python được sử dụng hiệu quả trong môi trường đa xử lý với các kỹ thuật đa luồng và trong khi các giải pháp khác đều có thể gặp vấn đề về hiệu năng.

  • Python không có cơ chế xác định việc sử dụng các đối tượng giá trị; tất cả mọi thứ được xử lý bằng cách tham chiếu, thêm phần bổ sung trong trường hợp không nhất thiết phải có. Mặc dù trình biên dịch JIT có thể suy ra các đối tượng giá trị trong một số trường hợp và tự động tối ưu hóa điều này, nhưng không thể làm như vậy nói chung và do đó mã không được viết cẩn thận để đảm bảo tối ưu hóa (có thể là một nghệ thuật đen) sẽ chịu đựng.

  • Python có một evalhàm, có nghĩa là trình biên dịch JIT không thể đưa ra các giả định về các hành động không xảy ra, ngay cả khi nó thực hiện phân tích toàn bộ chương trình, miễn là evalđược sử dụng một lần. Ví dụ, trình biên dịch Python không thể giả định rằng một lớp không có các lớp con và do đó làm sai lệch các cuộc gọi phương thức, bởi vì giả định đó sau đó có thể bị phủ định thông qua một cuộc gọi đến eval. Thay vào đó, nó phải thực hiện kiểm tra kiểu động để đảm bảo rằng các giả định được tạo bởi mã được biên dịch riêng không bị vô hiệu trước khi thực thi mã đó.


3
Điểm thứ hai có thể được giảm thiểu bằng cách evalkích hoạt biên dịch lại và / hoặc tối ưu hóa.
Jörg W Mittag

4
Nhân tiện, đó cũng không phải là duy nhất đối với Python. Java (hay đúng hơn là JVM) có tải mã động và liên kết động, do đó Phân tích phân cấp lớp cũng tương đương với việc giải quyết vấn đề dừng ở đó. Tuy nhiên, HotSpot vui vẻ suy đoán một cách cụ thể các phương thức đa hình và nếu một cái gì đó trong hệ thống phân cấp lớp thay đổi, thì nó sẽ chỉ loại bỏ chúng trở lại.
Jörg W Mittag
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.