2013-07-26 38 views
12

Gần đây tôi đã sử dụng python ngày càng nhiều thay cho c/C++ vì nó cắt giảm thời gian mã hóa của tôi bằng một vài yếu tố. Đồng thời, khi tôi xử lý một lượng lớn dữ liệu, tốc độ mà các chương trình python của tôi chạy bắt đầu trở nên chậm hơn rất nhiều so với trong c. Tôi tự hỏi nếu điều này là do tôi sử dụng các đối tượng lớn/mảng không hiệu quả. Có hướng dẫn toàn diện nào về cách bộ nhớ được xử lý bởi numpy/python không? Khi mọi thứ được chuyển qua tham chiếu và khi theo giá trị, khi mọi thứ được sao chép và khi không, loại nào có thể thay đổi được và loại nào không.python numpy và hiệu quả bộ nhớ (vượt qua tham chiếu và giá trị)

+9

"Yếu tố của một vài" là thuật ngữ kỹ thuật mới của tôi để nói chuyện với nhân viên phi kỹ thuật về lý do tại sao chúng tôi nên chuyển sang Python. – BlackVegetable

+4

[Bài đăng này] (http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference) có số lượng dữ liệu liên quan đến thần thánh cho câu hỏi này ... – jdero

+0

@ jdero Điều đó có nghĩa là về cơ bản nó hoạt động giống hệt Java, đúng không? – BlackVegetable

Trả lời

1

Vì vậy, tôi sẽ phải trích dẫn EOL về vấn đề này vì tôi nghĩ rằng câu trả lời của ông là rất có liên quan:

3) Vấn đề cuối cùng liên quan đến tiêu đề câu hỏi: "đi ngang qua giá trị" và "truyền qua tham chiếu" không phải là các khái niệm có liên quan trong Python. Các khái niệm có liên quan thay vào đó là "đối tượng có thể thay đổi" và "đối tượng không thay đổi". Danh sách có thể thay đổi, trong khi số không, trong đó giải thích những gì bạn quan sát. Ngoài ra, đối tượng Person1 và bar1 của bạn là có thể thay đổi (đó là lý do tại sao bạn có thể thay đổi tuổi của người đó). Bạn có thể tìm thấy thêm thông tin khác về các khái niệm này trong hướng dẫn bằng văn bản và video hướng dẫn . Wikipedia cũng có một số thông tin (kỹ thuật hơn). Một ví dụ minh họa sự khác biệt về hành vi giữa có thể thay đổi và bất biến - answer by EOL

Nói chung tôi đã tìm thấy NumPy/scipy theo các; quan trọng hơn là họ nói với bạn một cách rõ ràng trong tài liệu những gì đang xảy ra.

Ví dụ: np.random.shuffle yêu cầu mảng đầu vào và trả về None trong khi np.random.permutation trả về một mảng. Bạn có thể thấy rõ cái nào trả về một giá trị so với không ở đây.

Các mảng Simiarly có ngữ nghĩa học theo tham chiếu và nói chung tôi thấy Numpy/Scipy là rất hiệu quả.

Tôi nghĩ thật công bằng khi nói rằng nếu sử dụng nhanh hơn pass-by-reference thì sẽ tốt hơn. Miễn là bạn sử dụng các chức năng theo cách các tài liệu nói, bạn không nên có vấn đề đáng kể liên quan đến tốc độ.


có bất kỳ loại cụ thể nào mà bạn đang yêu cầu không?

+0

Cảm ơn câu trả lời của bạn. Không, không có loại thực sự cụ thể mà tôi đang cân nhắc; Tôi đã tìm kiếm thêm một câu trả lời về các kiểu mã hóa chung, tối ưu để sử dụng cho hiệu quả tính toán. Tôi nghĩ rằng điều này có thể không tồn tại cho python, bên cạnh việc tin tưởng rằng các phương pháp numpy/scipy đã được tối ưu hóa. – DilithiumMatrix

+0

Xin lỗi trong python chung đã được thực hiện cho dễ dàng không tốc độ :). Tuy nhiên, bạn có thể viết các phần mà bạn muốn 'nhanh' trong C và gọi chúng bằng Python để đạt được các thời gian chạy nhanh, hoặc luôn luôn có tính chất sần sùi/scipy như bạn nói.Đồng thời biên dịch gọn gàng/scipy cho bản dựng cụ thể của bạn có thể giúp tối ưu hóa chúng hơn nữa! –

8

Đối tượng bằng python (và hầu hết các ngôn ngữ chính) được chuyển làm tham chiếu.

Nếu chúng ta lấy một phần, ví dụ, các mảng "mới" được tạo bằng cách lập chỉ mục các mảng hiện tại chỉ là các khung nhìn của bản gốc. Ví dụ:

import numpy as np 

>>> vec_1 = np.array([range(10)]) 
>>> vec_1 
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 
>>> vec_2 = vec_1[3:] # let vec_2 be vec_1 from the third element untill the end 
>>> vec_2 
array([3, 4, 5, 6, 7, 8, 9]) 
>>> vec_2[3] = 10000 
array([3, 4, 5, 10000, 7, 8, 9]) 
>>> vec_1 
array([0, 1, 2, 3, 4, 5, 10000, 7, 8, 9]) 

Numpy có một phương pháp tiện dụng để giúp giải đáp các thắc mắc của bạn, được gọi là may_share_memory (obj1, obj2). Vì vậy:

>>> np.may_share_memory(vec_1, vec_2) 
True 

Chỉ cần cẩn thận, vì có thể cho phương pháp trả lại dương tính giả (Mặc dù tôi chưa bao giờ thấy một mặt hàng).

Tại SciPy 2013, có hướng dẫn về numpy (http://conference.scipy.org/scipy2013/tutorial_detail.php?id=100). Cuối cùng chàng trai nói một chút về cách xử lý bộ nhớ gumpy. Xem nó.

Theo quy tắc chung, các đối tượng hầu như không bao giờ được chuyển làm giá trị theo mặc định. Ngay cả những người đóng gói trên một đối tượng khác. Một ví dụ khác, trong đó danh sách tạo chuyến tham quan:

Class SomeClass(): 

    def __init__(a_list): 
     self.inside_list = a_list 

    def get_list(self): 
     return self.inside_list 

>>> original_list = range(5) 
>>> original_list 
[0,1,2,3,4] 
>>> my_object = SomeClass(original_list) 
>>> output_list = my_object.get_list() 
>>> output_list 
[0,1,2,3,4] 
>>> output_list[4] = 10000 
>>> output_list 
[0,1,2,3,10000] 
>>> my_object.original_list 
[0,1,2,3,10000] 
>>> original_list 
[0,1,2,3,10000] 

Đáng sợ, phải không? Sử dụng ký hiệu gán ("=") hoặc trả về một ở cuối hàm, bạn sẽ luôn tạo một con trỏ tới đối tượng hoặc một phần của nó. Đối tượng chỉ được nhân đôi khi bạn làm như vậy, sử dụng phương thức sao chép như some_dict.copy hoặc mảng [:]. Ví dụ:

>>> original_list = range(5) 
>>> original_list 
[0,1,2,3,4] 
>>> my_object = SomeClass(original_list[:]) 
>>> output_list = my_object.get_list() 
>>> output_list 
[0,1,2,3,4] 
>>> output_list[4] = 10000 
>>> output_list 
[0,1,2,3,10000] 
>>> my_object.original_list 
[0,1,2,3,10000] 
>>> original_list 
[0,1,2,3,4] 

OK?

+0

Tôi nghĩ rằng trong ví dụ cuối cùng của bạn 'my_object.original_list' phải là' my_object.get_list() '. Ngoài ra, bạn có thể muốn thêm cách 'vec2 [:]' hoạt động so với 'vec2' khi một giá trị được gán cho chúng trong ví dụ đầu tiên của bạn –

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