Hướng dẫn does static typing make python faster? - nhập tĩnh có làm cho python nhanh hơn không?

5

Mới! Lưu câu hỏi hoặc câu trả lời và sắp xếp nội dung yêu thích của bạn. Tìm hiểu thêm.
Learn more.

Gần đây, Python 3.6 đã thêm gõ tĩnh như một cách để thực thi một số loại. Chức năng tương tự này tôi đã sử dụng để có được nó từ Cython, có được các chức năng được tối ưu hóa cao khi so sánh với Vanilla Python.

Câu hỏi của tôi sau đó là: Chúng ta cũng sẽ tăng hiệu suất đáng kể khi sử dụng gõ tĩnh Python mới? Ưu/nhược điểm của mỗi phương pháp?

Hỏi ngày 8 tháng 8 năm 2018 lúc 9:20Aug 8, 2018 at 9:20

0

Gõ tĩnh trong Python không biến nó thành ngôn ngữ lập trình được biên dịch. Do đó, hiệu suất khôn ngoan, bạn nên luôn luôn có được hiệu suất tốt hơn từ Cython [được biên dịch phải luôn luôn đánh bại diễn giải].

Mục đích chính của việc đánh máy tĩnh mới được thêm vào của Python là thực hiện kiểm tra loại theo cách liền mạch, Bys hy sinh một số triết lý của Python trên đường đi.

Tóm lại: Cython cho tốc độ, Python3.6 cho phương pháp giải thích/pythonic hơn.: Cython for speed, Python3.6 for interpreted/more pythonic approach.

Đã trả lời ngày 8 tháng 8 năm 2018 lúc 9:26Aug 8, 2018 at 9:26

1

Không có gõ tĩnh trong bất kỳ phiên bản hiện có của CPython, 3.7 trở lên.static typing in any existing version of CPython, 3.7 or earlier.

Sự hỗ trợ cho các chú thích loại tùy chọn trong CPython 3.6 [cũng được đặt lại đến 3.5] giúp các công cụ bên ngoài như máy phân tích mã tĩnh xác minh rằng các loại được sử dụng một cách nhất quán trong một chương trình.type annotations in CPython 3.6 [backported to 3.5 as well] helps the external tools such as static code analysers to verify that types are used consistently in a program.

Loại gợi ý không có tác động đến việc biên dịch hoặc thực thi mã byte.

Từ CPython 3.6 có gì mới:

Trái ngược với các khai báo biến trong các ngôn ngữ được đánh máy tĩnh, mục tiêu của cú pháp chú thích là cung cấp một cách dễ dàng để chỉ định siêu dữ liệu loại có cấu trúc cho các công cụ và thư viện của bên thứ ba thông qua cây cú pháp trừu tượng và thuộc tính chú thích.annotations attribute.

Lưu ý rằng tuy nhiên, cú pháp gợi ý loại có thể được sử dụng trong Cython để xác định các loại C [Cú pháp khai báo loại].

Đã trả lời ngày 8 tháng 8 năm 2018 lúc 9:27Aug 8, 2018 at 9:27

Oleh Rybalchenkooleh RybalchenkoOleh Rybalchenko

5,8683 Huy hiệu vàng20 Huy hiệu bạc35 Huy hiệu Đồng3 gold badges20 silver badges35 bronze badges

Phiên bản này của tài liệu này dành cho chi nhánh phát triển mới nhất và lớn nhất của Cython. Đối với phiên bản phát hành cuối cùng, xem tại đây.

Ghi chú

Trang này sử dụng hai biến thể cú pháp khác nhau:

  • Cú pháp cụ thể của Cython, được thiết kế để làm cho các khai báo loại 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 loại Cython tĩnh trong mã python thuần túy, theo gợi ý loại PEP-484 và các chú thích biến PEP 526.pure Python code, following PEP-484 type hints and PEP 526 variable annotations.

    Để sử dụng các loại dữ liệu C trong cú pháp Python, bạn cần nhập mô -đun cython đặc biệt trong mô -đun Python mà bạn muốn biên dịch, ví dụ:

Cython là một trình biên dịch Python. Điều này có nghĩa là nó có thể biên dịch mã python bình thường mà không thay đổi [với một vài ngoại lệ rõ ràng về một số tính năng ngôn ngữ chưa được hỗ trợ, xem các hạn chế của Cython]. Tuy nhiên, đối với mã quan trọng hiệu suất, thường rất hữu ích khi thêm các khai báo loại tĩnh, vì chúng sẽ cho phép Cython bước ra khỏi bản chất động của mã Python và tạo mã C đơn giản hơn và nhanh hơn - đôi khi nhanh hơn theo thứ tự cường độ.Cython limitations]. However, for performance critical code, it is often helpful to add static type declarations, as they will allow Cython to step out of the dynamic nature of the Python code and generate simpler and faster C code - sometimes faster by orders of magnitude.

Tuy nhiên, cần lưu ý rằng các khai báo loại có thể làm cho mã nguồn nhiều dòng hơn và do đó không thể đọc được. Do đó, không khuyến khích sử dụng chúng mà không có lý do chính đáng, chẳng hạn như nơi điểm chuẩn chứng minh rằng chúng thực sự làm cho mã nhanh hơn đáng kể trong phần quan trọng hiệu suất. Thông thường một vài loại ở đúng điểm đi một chặng đường dài.

Tất cả các loại C đều có sẵn cho các loại khai báo loại: các loại điểm số nguyên và nổi, số phức, cấu trúc, công đoàn và loại con trỏ. Cython có thể tự động chuyển đổi và chính xác giữa các loại về gán. Điều này cũng bao gồm các loại số nguyên kích thước tùy ý của Python, trong đó giá trị tràn khi chuyển đổi sang loại C sẽ tăng Python OverflowError khi chạy. [Tuy nhiên, nó không kiểm tra tràn khi thực hiện số học.] Mã C được tạo sẽ xử lý các kích thước phụ thuộc nền tảng của các loại C một cách chính xác và an toàn trong trường hợp này.

Các loại được khai báo thông qua từ khóa CDEF.

Gõ các biến

Hãy xem xét mã Python thuần túy sau:

Tích hợp.py¶

def f[x]:
    return x ** 2 - x


def integrate_f[a, b, N]:
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx

Đơn giản chỉ cần biên dịch điều này ở Cython chỉ đơn thuần là tăng tốc 35%. Điều này tốt hơn là không có gì, nhưng thêm một số loại tĩnh có thể tạo ra sự khác biệt lớn hơn nhiều.

Với các khai báo loại bổ sung, điều này có thể trông giống như:

Tích hợp_cy.py¶

def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx

Do biến Iterator i được gõ bằng chữ C, nên vòng lặp sẽ được biên dịch thành mã C thuần túy. Gõ a, sdx rất quan trọng vì chúng có liên quan đến số học trong vòng lặp; Gõ

def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
0 và
def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
1 làm cho ít sự khác biệt hơn, nhưng trong trường hợp này, nó không có nhiều công việc để nhất quán và gõ toàn bộ chức năng.

Điều này dẫn đến tăng tốc 4 lần so với phiên bản Python thuần túy.

Chức năng gõ

Các cuộc gọi chức năng Python có thể tốn kém - trong Cython gấp đôi vì vậy người ta có thể cần phải chuyển đổi đến và từ các đối tượng Python để thực hiện cuộc gọi. Trong ví dụ của chúng tôi ở trên, đối số được coi là một c gấp đôi cả bên trong

def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
2 và trong cuộc gọi đến nó, nhưng một đối tượng Python
def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
3 phải được xây dựng xung quanh đối số để vượt qua nó.

Do đó, Cython cung cấp một cách để khai báo chức năng kiểu C, tuyên bố cụ thể của Cython, cũng như trình trang trí

def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
5 để khai báo các chức năng kiểu C trong cú pháp Python. Cả hai cách tiếp cận đều tương đương và tạo ra cùng một mã C:

@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x

Một số hình thức của bộ biến đổi ngoại trừ thường nên được thêm vào, nếu không, Cython sẽ không thể tuyên truyền các ngoại lệ được nêu trong hàm [hoặc một hàm mà nó gọi].

def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
6 có nghĩa là một lỗi sẽ được kiểm tra nếu
def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
7 được trả về [mặc dù
def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
8 chỉ ra rằng
def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
7 cũng có thể được sử dụng làm giá trị trả về hợp lệ]. Điều tương tự có thể được thể hiện chỉ bằng cách sử dụng cú pháp Python với bộ trang trí
@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x
0.

Ngoài ra,

@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x
1 chậm hơn luôn an toàn. Một mệnh đề ngoại trừ có thể bị bỏ lại nếu hàm trả về một đối tượng Python hoặc nếu nó được đảm bảo rằng một ngoại lệ sẽ không được nêu trong cuộc gọi chức năng. Một lần nữa, Cython cung cấp cho người trang trí
@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x
2 cung cấp chức năng tương tự.

Một tác dụng phụ của cdef [và người trang trí

def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
5] là chức năng không còn được nhìn thấy từ không gian Python, như Python sẽ không biết cách gọi nó. Cũng không còn có thể thay đổi
def f[x: cython.double]:
    return x ** 2 - x


def integrate_f[a: cython.double, b: cython.double, N: cython.int]:
    i: cython.int
    s: cython.double
    dx: cython.double
    s = 0
    dx = [b - a] / N
    for i in range[N]:
        s += f[a + i * dx]
    return s * dx
2 khi chạy.

Sử dụng từ khóa

@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x
6 thay vì cdef, trình bao bọc Python cũng được tạo, để hàm có sẵn cả từ Cython [nhanh, truyền trực tiếp các giá trị được đánh máy] và từ Python [kết thúc các giá trị trong các đối tượng Python]. Trên thực tế,
@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x
6 không chỉ cung cấp trình bao bọc Python, nó còn cài đặt logic để cho phép phương thức được ghi đè bởi các phương thức Python, ngay cả khi được gọi từ bên trong Cython. Điều này không thêm một chi phí nhỏ so với các phương pháp cdef. Một lần nữa, Cython cung cấp một trình trang trí cdef0 cung cấp chức năng tương tự như từ khóa
@cython.cfunc
@cython.exceptval[-2, check=True]
def f[x: cython.double] -> cython.double:
    return x ** 2 - x
6.

Tăng tốc: 150 lần so với Python thuần túy.

Xác định nơi để thêm các loại

Bởi vì gõ tĩnh thường là chìa khóa để tăng tốc độ lớn, người mới bắt đầu thường có xu hướng gõ mọi thứ trong tầm nhìn. Điều này cắt giảm cả khả năng đọc và tính linh hoạt, và thậm chí có thể làm chậm mọi thứ [ví dụ: bằng cách thêm kiểm tra loại không cần thiết, chuyển đổi hoặc giải nén bộ đệm chậm]. Mặt khác, thật dễ dàng để tiêu diệt hiệu suất bằng cách quên gõ một biến vòng lặp quan trọng. Hai công cụ cần thiết để giúp với nhiệm vụ này là hồ sơ và chú thích. Hồ sơ phải là bước đầu tiên của bất kỳ nỗ lực tối ưu hóa nào và có thể cho bạn biết bạn đang dành thời gian ở đâu. Chú thích của Cython sau đó có thể cho bạn biết lý do tại sao mã của bạn mất thời gian.

Sử dụng chuyển đổi cdef2 sang chương trình dòng lệnh cython [hoặc theo liên kết từ SAGE Notebook] dẫn đến báo cáo HTML về mã Cython xen kẽ với mã C được tạo. Các dòng được tô màu theo mức độ của sự đánh máy của người Hồi giáo-các dòng màu trắng chuyển thành C thuần khiết, trong khi các dòng yêu cầu Python C-API có màu vàng [tối hơn khi chúng chuyển sang tương tác C-API nhiều hơn]. Các dòng dịch sang mã C có điểm cộng [cdef4] ở phía trước và có thể được nhấp để hiển thị mã được tạo.

Báo cáo này là vô giá khi tối ưu hóa một hàm cho tốc độ và để xác định khi nào nên phát hành GIL: Nói chung, một khối cdef5 có thể chỉ chứa mã trắng của Hồi.release the GIL: in general, a cdef5 block may contain only “white” code.

Lưu ý rằng Cython suy ra loại biến cục bộ dựa trên các bài tập của chúng [bao gồm cả mục tiêu biến vòng lặp] cũng có thể cắt giảm nhu cầu chỉ định rõ ràng các loại ở mọi nơi. Ví dụ: tuyên bố dx là loại gấp đôi ở trên là không cần thiết, như là tuyên bố loại s trong phiên bản cuối cùng [trong đó loại trả về của cdef8 được biết là một c Double.] Được sử dụng trong các biểu thức số học, vì Cython không thể đảm bảo rằng một luồng tràn sẽ không xảy ra [và do đó rơi trở lại cdef9 trong trường hợp Bignums của Python là cần thiết]. Để cho phép suy luận của các loại số nguyên C, hãy đặt lệnh cython0 thành cython1. Chỉ thị này thực hiện một công việc tương tự như từ khóa cython2 trong C ++ cho những người đọc quen thuộc với tính năng ngôn ngữ này. Nó có thể giúp đỡ rất nhiều để cắt giảm nhu cầu gõ mọi thứ, nhưng nó cũng có thể dẫn đến những bất ngờ. Đặc biệt nếu một người không quen thuộc với các biểu thức số học với các loại C. Một cái nhìn tổng quan nhanh về những người có thể được tìm thấy ở đây.directive to cython1. This directive does a work similar to the cython2 keyword in C++ for the readers who are familiar with this language feature. It can be of great help to cut down on the need to type everything, but it also can lead to surprises. Especially if one isn’t familiar with arithmetic expressions with c types. A quick overview of those can be found here.

Các ngôn ngữ được đánh máy tĩnh có nhanh hơn không?

Nói chung, các ngôn ngữ được gõ tĩnh sẽ thực hiện nhanh hơn các ngôn ngữ được đánh máy động vì các hệ thống loại của chúng được triển khai tại thời gian biên dịch thay vì thời gian chạy, vì vậy tất cả các công việc liên quan chỉ được thực hiện một lần.statically typed languages will execute faster than dynamically typed ones because their type systems are implemented at compile-time rather than run-time, so all the work involved is performed once only.

Gõ tĩnh có nhanh hơn gõ động không?

Các ngôn ngữ được gõ tĩnh thường nhanh hơn các ngôn ngữ được gõ động, nhưng không phải lúc nào cũng vậy.OBJC là một ngôn ngữ năng động và thường được coi là Java nhanh hơn.. ObjC is a dynamic language and generally considered faster the Java.

Python có sử dụng gõ tĩnh không?

Ngày 8 tháng 3 năm 2021 Python là một ngôn ngữ được đánh máy động.Người ta không phải chỉ ra một cách rõ ràng kiểu dữ liệu và các loại trả về của các biến và hàm của bạn, tương ứng.Gõ động làm cho Python rất thân thiện với người dùng.Python is a dynamically typed language. One does not have to explicitly indicate the data type and return types of your variables and functions, respectively. Dynamic typing makes Python very user-friendly.

Việc gõ tĩnh có làm giảm lỗi không?

Trong trại gõ tĩnh, chúng tôi có lợi ích của việc bắt lỗi sớm hơn trong chu kỳ phát triển, loại bỏ hoàn toàn một số loại lỗi trong các hệ thống được triển khai, cải thiện những thứ như hỗ trợ mã và hỗ trợ công cụ khác và cho phép tối ưu hóa trình biên dịch.eliminating altogether some classes of bugs in deployed systems, improved things like code-assist and other tool support, and enabling compiler optimisations.

Bài Viết Liên Quan

Chủ Đề