2012-02-09 48 views
9

Tôi cần thực hiện một số phép tính một danh sách lớn các số.mảng numpy Python vs danh sách

Do array.array hoặc numpy.array có tăng hiệu suất đáng kể so với mảng thông thường không?

Tôi không phải làm thao tác phức tạp trên các mảng, tôi chỉ cần để có thể truy cập và sửa đổi các giá trị,

ví dụ

import numpy 
x = numpy.array([0] * 1000000) 
for i in range(1,len(x)): 
    x[i] = x[i-1] + i 

Vì vậy, tôi sẽ không thực sự được cần nối, cắt, vv

Ngoài ra, nó trông giống như mảng ném một lỗi nếu tôi cố gắng gán giá trị không phù hợp trong C dài:

import numpy 
a = numpy.array([0]) 
a[0] += 1232234234234324353453453 
print(a) 

Mở console tôi nhận được:

a[0] += 1232234234234324353453453 
OverflowError: Python int too large to convert to C long 

có một biến thể của mảng cho phép tôi đưa vào unbo số nguyên Python chưa được xử lý? Hoặc sẽ làm theo cách đó lấy đi điểm có mảng ở nơi đầu tiên?

+0

Xem thêm [cpython vs cython vs hiệu suất mảng numpy] (http://stackoverflow.com/questions/22514730/cpython-vs-cython-vs-numpy-array-performance) – Trilarion

Trả lời

8

Ví dụ đầu tiên của bạn có thể tăng tốc. Vòng lặp Python và truy cập vào các mục riêng lẻ trong một mảng numpy là chậm. Sử dụng hoạt động vectorized thay vì:

import numpy as np 
x = np.arange(1000000).cumsum() 

Bạn có thể đặt số nguyên Python vô biên để mảng NumPy:

a = np.array([0], dtype=object) 
a[0] += 1232234234234324353453453 

hoạt động số học so với số nguyên C cố định cỡ sẽ chậm hơn trong trường hợp này.

11

Trước tiên, bạn cần hiểu sự khác biệt giữa các mảng và danh sách.

Mảng là liền kề khối bộ nhớ bao gồm các phần tử của một số loại (ví dụ: số nguyên).

Bạn không thể thay đổi kích thước của mảng khi nó được tạo.
Do đó, sau đó mỗi phần tử nguyên trong một mảng có kích thước cố định , ví dụ: 4 byte.

Mặt khác, danh sách chỉ là một "mảng" gồm địa chỉ (cũng có kích thước cố định).

Nhưng sau đó mỗi yếu tố giữ địa chỉ của một cái gì đó khác trong bộ nhớ, đó là thực tế nguyên mà bạn muốn làm việc với. Tất nhiên, kích thước của số nguyên này không liên quan đến kích thước của mảng. Vì vậy, bạn luôn có thể tạo một số nguyên mới (lớn hơn) và "thay thế" số nguyên cũ mà không ảnh hưởng đến kích thước của mảng, chỉ giữ địa chỉ của một số nguyên.

Tất nhiên, sự tiện lợi này của một danh sách đi kèm với chi phí: Thực hiện số học trên số nguyên hiện yêu cầu truy cập bộ nhớ để mảng, cộng truy cập bộ nhớ đến số nguyên chính nó, cộng thời gian cần thiết để cấp thêm bộ nhớ (nếu cần), cộng thời gian cần thiết để xóa số nguyên cũ (nếu cần). Vì vậy, có, nó có thể chậm hơn, vì vậy bạn phải cẩn thận những gì bạn đang làm với mỗi số nguyên bên trong một mảng.

+0

Đoạn cuối cùng cũng áp dụng cho các mảng có nhiều mảng số nguyên có kích thước cố định nếu bạn không sử dụng các hoạt động được vector hóa (như trong ví dụ đầu tiên của OP). Đó là * không * lý do tại sao mảng numpy có thể nhanh hơn. – jfs

0

Do array.array hoặc numpy.array có tăng hiệu suất đáng kể so với mảng thông thường không?

Có thể, tùy thuộc vào việc bạn đang làm.

Hoặc sẽ làm theo cách đó lấy đi điểm có mảng ngay từ đầu?

Khá nhiều, vâng.

1

Do array.array hoặc numpy.array cung cấp tăng hiệu suất đáng kể trên mảng thông thường?

Tôi cố gắng để kiểm tra điều này một chút với đoạn mã sau:

import timeit, math, array 
from functools import partial 
import numpy as np 

# from the question 
def calc1(x): 
    for i in range(1,len(x)): 
     x[i] = x[i-1] + 1 

# a floating point operation 
def calc2(x): 
    for i in range(0,len(x)): 
     x[i] = math.sin(i) 

L = int(1e5) 

# np 
print('np 1: {:.5f} s'.format(timeit.timeit(partial(calc1, np.array([0] * L)), number=20))) 
print('np 2: {:.5f} s'.format(timeit.timeit(partial(calc2, np.array([0] * L)), number=20))) 

# np but with vectorized form 
vfunc = np.vectorize(math.sin) 
print('np 2 vectorized: {:.5f} s'.format(timeit.timeit(partial(vfunc, np.arange(0, L)), number=20))) 

# with list 
print('list 1: {:.5f} s'.format(timeit.timeit(partial(calc1, [0] * L), number=20))) 
print('list 2: {:.5f} s'.format(timeit.timeit(partial(calc2, [0] * L), number=20))) 

# with array 
print('array 1: {:.5f} s'.format(timeit.timeit(partial(calc1, array.array("f", [0] * L)), number=20))) 
print('array 2: {:.5f} s'.format(timeit.timeit(partial(calc2, array.array("f", [0] * L)), number=20))) 

Và kết quả là danh sách đó thực hiện nhanh nhất đây (Python 3.3, NumPy 1.8):

np 1: 2.14277 s 
np 2: 0.77008 s 
np 2 vectorized: 0.44117 s 
list 1: 0.29795 s 
list 2: 0.66529 s 
array 1: 0.66134 s 
array 2: 0.88299 s 

nào dường như phản trực giác. Dường như không có lợi thế nào khi sử dụng numpy hoặc array trên list cho các ví dụ đơn giản này.

0

sử dụng a=numpy.array(number_of_elements, dtype=numpy.int64) nên cung cấp cho bạn một loạt các số nguyên 64 bit. Đây có thể lưu trữ bất kỳ số nguyên giữa -2^63 và (2^63) -1 (khoảng giữa -10^19 và 10^19) mà thường là quá đủ.

2

Để sử dụng nhiều nhất, danh sách hữu ích. Đôi khi làm việc với các mảng có nhiều mảng có thể thuận tiện hơn chẳng hạn.

a=[1,2,3,4,5,6,7,8,9,10] 

b=[5,8,9] 

Hãy xem xét một danh sách 'a' và nếu bạn muốn truy cập vào các yếu tố trong một danh sách ở chỉ số rời rạc được đưa ra trong danh sách 'b' viết

b[a] 

sẽ không hoạt động.

nhưng khi bạn sử dụng chúng như mảng, bạn chỉ có thể viết

b[a] 

để có được kết quả như mảng ([6,9,10]).

Các vấn đề liên quan