Xóa mảng python numpy

Bạn có thể sử dụng NumPy từ Cython giống hệt như trong Python thông thường, nhưng làm như vậy bạn sẽ mất khả năng tăng tốc cao vì Cython có hỗ trợ truy cập nhanh vào mảng NumPy. Hãy xem cách nó hoạt động với một ví dụ đơn giản

Mã bên dưới thực hiện tích chập rời rạc 2D của hình ảnh bằng bộ lọc [và tôi chắc rằng bạn có thể làm tốt hơn. , hãy để nó phục vụ cho mục đích trình diễn]. Đó là cả Python hợp lệ và mã Cython hợp lệ. Tôi sẽ gọi nó là cả

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
8 cho phiên bản Python và
In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
0 cho phiên bản Cython – Cython sử dụng “. pyx” làm hậu tố tệp của nó

import numpy as np


def naive_convolve[f, g]:
    # f is an image and is indexed by [v, w]
    # g is a filter kernel and is indexed by [s, t],
    #   it needs odd dimensions
    # h is the output image and is indexed by [x, y],
    #   it is not cropped
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    # smid and tmid are number of pixels between the center pixel
    # and the edge, ie for a 5x5 filter they will be 2.
    #
    # The output size is calculated by adding smid, tmid to each
    # side of the dimensions of the input image.
    vmax = f.shape[0]
    wmax = f.shape[1]
    smax = g.shape[0]
    tmax = g.shape[1]
    smid = smax // 2
    tmid = tmax // 2
    xmax = vmax + 2 * smid
    ymax = wmax + 2 * tmid
    # Allocate result image.
    h = np.zeros[[xmax, ymax], dtype=f.dtype]
    # Do convolution
    for x in range[xmax]:
        for y in range[ymax]:
            # Calculate pixel value for h at [x,y]. Sum one component
            # for each pixel [s, t] of the filter g.
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h

Điều này nên được biên dịch để tạo ra

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
1 [đối với hệ thống Linux, trên hệ thống Windows, nó sẽ là
In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
2]. Chúng tôi chạy một phiên Python để kiểm tra cả phiên bản Python [được nhập từ tệp
In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
3] và mô-đun Cython đã biên dịch

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop

Vẫn chưa có sự khác biệt lớn như vậy; . Nhìn vào tệp html được tạo và xem những gì cần thiết cho ngay cả những câu lệnh đơn giản nhất mà bạn sẽ hiểu nhanh chóng. Chúng tôi cần cung cấp thêm thông tin cho Cython;

Thêm loại¶

Để thêm các loại, chúng tôi sử dụng cú pháp Cython tùy chỉnh, vì vậy chúng tôi hiện đang phá vỡ khả năng tương thích nguồn Python. Hãy xem xét mã này [đọc các bình luận. ]

# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h

Sau khi xây dựng điều này và tiếp tục các điểm chuẩn [rất không chính thức] của tôi, tôi nhận được

In [21]: import convolve2
In [22]: %timeit -n2 -r3 convolve2.naive_convolve[f, g]
2 loops, best of 3: 828 ms per loop

Lập chỉ mục hiệu quả¶

Vẫn còn một điểm hạn chế về hiệu suất, đó là tra cứu mảng và gán. Toán tử

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
4 vẫn sử dụng đầy đủ các thao tác Python – thay vào đó, điều chúng tôi muốn làm là truy cập trực tiếp vào bộ đệm dữ liệu ở tốc độ C

Điều chúng ta cần làm sau đó là gõ nội dung của đối tượng

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
5. Chúng tôi thực hiện điều này với một cú pháp "bộ đệm" đặc biệt phải được cho biết kiểu dữ liệu [đối số đầu tiên] và số thứ nguyên [đối số chỉ từ khóa ["ndim"], nếu không được cung cấp thì giả định một chiều]

Đây là những thay đổi cần thiết

import numpy as np


def naive_convolve[f, g]:
    # f is an image and is indexed by [v, w]
    # g is a filter kernel and is indexed by [s, t],
    #   it needs odd dimensions
    # h is the output image and is indexed by [x, y],
    #   it is not cropped
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    # smid and tmid are number of pixels between the center pixel
    # and the edge, ie for a 5x5 filter they will be 2.
    #
    # The output size is calculated by adding smid, tmid to each
    # side of the dimensions of the input image.
    vmax = f.shape[0]
    wmax = f.shape[1]
    smax = g.shape[0]
    tmax = g.shape[1]
    smid = smax // 2
    tmid = tmax // 2
    xmax = vmax + 2 * smid
    ymax = wmax + 2 * tmid
    # Allocate result image.
    h = np.zeros[[xmax, ymax], dtype=f.dtype]
    # Do convolution
    for x in range[xmax]:
        for y in range[ymax]:
            # Calculate pixel value for h at [x,y]. Sum one component
            # for each pixel [s, t] of the filter g.
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
0

Cách sử dụng

import numpy as np


def naive_convolve[f, g]:
    # f is an image and is indexed by [v, w]
    # g is a filter kernel and is indexed by [s, t],
    #   it needs odd dimensions
    # h is the output image and is indexed by [x, y],
    #   it is not cropped
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    # smid and tmid are number of pixels between the center pixel
    # and the edge, ie for a 5x5 filter they will be 2.
    #
    # The output size is calculated by adding smid, tmid to each
    # side of the dimensions of the input image.
    vmax = f.shape[0]
    wmax = f.shape[1]
    smax = g.shape[0]
    tmax = g.shape[1]
    smid = smax // 2
    tmid = tmax // 2
    xmax = vmax + 2 * smid
    ymax = wmax + 2 * tmid
    # Allocate result image.
    h = np.zeros[[xmax, ymax], dtype=f.dtype]
    # Do convolution
    for x in range[xmax]:
        for y in range[ymax]:
            # Calculate pixel value for h at [x,y]. Sum one component
            # for each pixel [s, t] of the filter g.
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
1

Lưu ý tầm quan trọng của thay đổi này

Gotcha. Việc lập chỉ mục hiệu quả này chỉ ảnh hưởng đến một số hoạt động lập chỉ mục nhất định, cụ thể là những hoạt động có chính xác số lượng chỉ mục số nguyên đã nhập

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
6. Vì vậy, nếu chẳng hạn như
In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
7 không được nhập, thì tra cứu
In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
8 không được tối ưu hóa. Mặt khác, điều này có nghĩa là bạn có thể tiếp tục sử dụng các đối tượng Python để cắt động tinh vi, v.v. giống như khi mảng không được gõ

Điều chỉnh lập chỉ mục hơn nữa¶

Việc tra cứu mảng vẫn bị chậm lại bởi hai yếu tố

  1. Kiểm tra giới hạn được thực hiện

  2. Các chỉ số tiêu cực được kiểm tra và xử lý chính xác. Đoạn mã trên được mã hóa rõ ràng để nó không sử dụng các chỉ số phủ định và [hy vọng] nó luôn truy cập trong giới hạn. Chúng tôi có thể thêm một trình trang trí để tắt kiểm tra giới hạn

    import numpy as np
    
    
    def naive_convolve[f, g]:
        # f is an image and is indexed by [v, w]
        # g is a filter kernel and is indexed by [s, t],
        #   it needs odd dimensions
        # h is the output image and is indexed by [x, y],
        #   it is not cropped
        if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
            raise ValueError["Only odd dimensions on filter supported"]
        # smid and tmid are number of pixels between the center pixel
        # and the edge, ie for a 5x5 filter they will be 2.
        #
        # The output size is calculated by adding smid, tmid to each
        # side of the dimensions of the input image.
        vmax = f.shape[0]
        wmax = f.shape[1]
        smax = g.shape[0]
        tmax = g.shape[1]
        smid = smax // 2
        tmid = tmax // 2
        xmax = vmax + 2 * smid
        ymax = wmax + 2 * tmid
        # Allocate result image.
        h = np.zeros[[xmax, ymax], dtype=f.dtype]
        # Do convolution
        for x in range[xmax]:
            for y in range[ymax]:
                # Calculate pixel value for h at [x,y]. Sum one component
                # for each pixel [s, t] of the filter g.
                s_from = max[smid - x, -smid]
                s_to = min[[xmax - x] - smid, smid + 1]
                t_from = max[tmid - y, -tmid]
                t_to = min[[ymax - y] - tmid, tmid + 1]
                value = 0
                for s in range[s_from, s_to]:
                    for t in range[t_from, t_to]:
                        v = x - smid + s
                        w = y - tmid + t
                        value += g[smid - s, tmid - t] * f[v, w]
                h[x, y] = value
        return h
    
    5

Hiện tại, việc kiểm tra giới hạn không được thực hiện [và, như một tác dụng phụ, nếu bạn ''làm'' truy cập ngoài giới hạn, trong trường hợp tốt nhất, bạn sẽ làm hỏng chương trình của mình và trong trường hợp xấu nhất là dữ liệu bị hỏng]. Có thể chuyển chế độ kiểm tra giới hạn theo nhiều cách, xem Chỉ thị trình biên dịch để biết thêm thông tin.

Ngoài ra, chúng tôi đã vô hiệu hóa việc kiểm tra để bọc các chỉ số âm [e. g. g[-1] đưa ra giá trị cuối cùng]. Như với việc vô hiệu hóa kiểm tra giới hạn, điều tồi tệ sẽ xảy ra nếu chúng ta thực sự cố gắng sử dụng các chỉ số phủ định với việc vô hiệu hóa này

Chi phí cuộc gọi chức năng bây giờ bắt đầu đóng một vai trò, vì vậy chúng tôi so sánh hai ví dụ sau với N lớn hơn

import numpy as np


def naive_convolve[f, g]:
    # f is an image and is indexed by [v, w]
    # g is a filter kernel and is indexed by [s, t],
    #   it needs odd dimensions
    # h is the output image and is indexed by [x, y],
    #   it is not cropped
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    # smid and tmid are number of pixels between the center pixel
    # and the edge, ie for a 5x5 filter they will be 2.
    #
    # The output size is calculated by adding smid, tmid to each
    # side of the dimensions of the input image.
    vmax = f.shape[0]
    wmax = f.shape[1]
    smax = g.shape[0]
    tmax = g.shape[1]
    smid = smax // 2
    tmid = tmax // 2
    xmax = vmax + 2 * smid
    ymax = wmax + 2 * tmid
    # Allocate result image.
    h = np.zeros[[xmax, ymax], dtype=f.dtype]
    # Do convolution
    for x in range[xmax]:
        for y in range[ymax]:
            # Calculate pixel value for h at [x,y]. Sum one component
            # for each pixel [s, t] of the filter g.
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
6

[Ngoài ra, đây là một điểm chuẩn hỗn hợp vì mảng kết quả được phân bổ trong lệnh gọi hàm. ]

Cảnh báo

Tốc độ đi kèm với một số chi phí. Đặc biệt có thể nguy hiểm khi đặt các đối tượng đã nhập [như

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
9,
# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
0 và
# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
1 trong mã mẫu của chúng tôi] thành
# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
2. Đặt các đối tượng như vậy thành
# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
2 là hoàn toàn hợp pháp, nhưng tất cả những gì bạn có thể làm với chúng là kiểm tra xem chúng có phải là Không. Tất cả các mục đích sử dụng khác [tra cứu thuộc tính hoặc lập chỉ mục] có thể có khả năng phân tách dữ liệu hoặc làm hỏng dữ liệu [thay vì đưa ra các ngoại lệ như trong Python]

Các quy tắc thực tế phức tạp hơn một chút nhưng thông điệp chính rất rõ ràng. Không sử dụng các đối tượng đã nhập mà không biết rằng chúng không được đặt thành Không có

Việc đánh máy không làm được¶

Mục đích chính của việc nhập những thứ dưới dạng

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
5 là để cho phép lập chỉ mục hiệu quả cho các phần tử đơn lẻ và tăng tốc độ truy cập vào một số lượng nhỏ các thuộc tính, chẳng hạn như
# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
5. Việc gõ không cho phép Cython tăng tốc các phép toán trên cả mảng [ví dụ cộng hai mảng lại với nhau]. Việc nhập không cho phép Cython tăng tốc các cuộc gọi đến các hàm toàn cầu của Numpy hoặc các phương thức của mảng

Mã chung hơn¶

Nó sẽ có thể làm

In [1]: import numpy as np
In [2]: import convolve_py
In [3]: convolve_py.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [3]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [4]: import convolve1
In [4]: convolve1.naive_convolve[np.array[[[1, 1, 1]], dtype=np.int],
..     np.array[[[1],[2],[1]], dtype=np.int]]
Out [4]:
array[[[1, 1, 1],
    [2, 2, 2],
    [1, 1, 1]]]
In [11]: N = 100
In [12]: f = np.arange[N*N, dtype=np.int].reshape[[N,N]]
In [13]: g = np.arange[81, dtype=np.int].reshape[[9, 9]]
In [19]: %timeit -n2 -r3 convolve_py.naive_convolve[f, g]
2 loops, best of 3: 1.86 s per loop
In [20]: %timeit -n2 -r3 convolve1.naive_convolve[f, g]
2 loops, best of 3: 1.41 s per loop
4

i. e. sử dụng

# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
6 thay vì
# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
7. Theo Python 3. 0, điều này có thể cho phép thuật toán của bạn hoạt động với bất kỳ thư viện nào hỗ trợ giao diện bộ đệm; . g. Thư viện hình ảnh Python có thể dễ dàng được thêm vào nếu ai đó cũng quan tâm đến Python 2. x

Tuy nhiên, có một số hình phạt về tốc độ đối với điều này [vì người ta đưa ra nhiều giả định hơn về thời gian biên dịch nếu loại được đặt thành

# tag: numpy
# You can ignore the previous line.
# It's for internal testing of the cython documentation.

import numpy as np

# "cimport" is used to import special compile-time information
# about the numpy module [this is stored in a file numpy.pxd which is
# currently part of the Cython distribution].
cimport numpy as np

# It's necessary to call "import_array" if you use any part of the
# numpy PyArray_* API. From Cython 3, accessing attributes like
# ".shape" on a typed Numpy array use this API. Therefore we recommend
# always calling "import_array" whenever you "cimport numpy"
np.import_array[]

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.int

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.int_t DTYPE_t

# "def" can type its arguments but not have a return type. The type of the
# arguments for a "def" function is checked at run-time when entering the
# function.
#
# The arrays f, g and h is typed as "np.ndarray" instances. The only effect
# this has is to a] insert checks that the function arguments really are
# NumPy arrays, and b] make some attribute access like f.shape[0] much
# more efficient. [In this example this doesn't matter though.]
def naive_convolve[np.ndarray f, np.ndarray g]:
    if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
        raise ValueError["Only odd dimensions on filter supported"]
    assert f.dtype == DTYPE and g.dtype == DTYPE

    # The "cdef" keyword is also used within functions to type variables. It
    # can only be used at the top indentation level [there are non-trivial
    # problems with allowing them in other places, though we'd love to see
    # good and thought out proposals for it].
    #
    # For the indices, the "int" type is used. This corresponds to a C int,
    # other C types [like "unsigned int"] could have been used instead.
    # Purists could use "Py_ssize_t" which is the proper Python type for
    # array indices.
    cdef int vmax = f.shape[0]
    cdef int wmax = f.shape[1]
    cdef int smax = g.shape[0]
    cdef int tmax = g.shape[1]
    cdef int smid = smax // 2
    cdef int tmid = tmax // 2
    cdef int xmax = vmax + 2 * smid
    cdef int ymax = wmax + 2 * tmid
    cdef np.ndarray h = np.zeros[[xmax, ymax], dtype=DTYPE]
    cdef int x, y, s, t, v, w

    # It is very important to type ALL your variables. You do not get any
    # warnings if not, only much slower code [they are implicitly typed as
    # Python objects].
    cdef int s_from, s_to, t_from, t_to

    # For the value variable, we want to use the same data type as is
    # stored in the array, so we use "DTYPE_t" as defined above.
    # NB! An important side-effect of this is that if "value" overflows its
    # datatype size, it will simply wrap around like in C, rather than raise
    # an error like in Python.
    cdef DTYPE_t value
    for x in range[xmax]:
        for y in range[ymax]:
            s_from = max[smid - x, -smid]
            s_to = min[[xmax - x] - smid, smid + 1]
            t_from = max[tmid - y, -tmid]
            t_to = min[[ymax - y] - tmid, tmid + 1]
            value = 0
            for s in range[s_from, s_to]:
                for t in range[t_from, t_to]:
                    v = x - smid + s
                    w = y - tmid + t
                    value += g[smid - s, tmid - t] * f[v, w]
            h[x, y] = value
    return h
7, cụ thể là giả định rằng dữ liệu được lưu trữ ở chế độ sải chân thuần túy chứ không phải ở chế độ gián tiếp]

Chủ Đề