2013-08-16 29 views
17

Tôi gặp vấn đề về bộ nhớ mà dường như tôi không hiểu.Giới hạn bộ nhớ 32 bit của Python trên các cửa sổ 64bit

Tôi đang ở trên một cửa sổ 7 máy 64 bit có bộ nhớ 8GB và chạy chương trình python 32 bit.

Các chương trình đọc 5.118 tệp nén gọn gàng (npz). Windows thông báo rằng các tập tin mất 1,98 GB trên đĩa

Mỗi tập tin npz chứa hai mẩu dữ liệu: 'arr_0' là loại np.float32 và 'arr_1' là loại np.uint8

Tập lệnh python đọc mỗi tệp nối dữ liệu của chúng vào hai danh sách và sau đó đóng tệp.

Khoảng tập 4284/5118 chương trình ném một MemoryException

Tuy nhiên, công việc quản lý nói rằng việc sử dụng bộ nhớ của python.exe * 32 khi lỗi xảy ra là 1,854,848K ~ = 1.8GB. Ít hơn giới hạn 8 GB của tôi, hoặc giới hạn 4GB của chương trình 32 bit.

Trong chương trình, tôi bắt được lỗi bộ nhớ và báo cáo: Mỗi danh sách có độ dài 4285. Danh sách đầu tiên chứa tổng số 1.928,588,480 float32 ~ = 229,9 MB dữ liệu. Danh sách thứ hai chứa 12.342.966,272 uint8 ~ = 1,471.3MB dữ liệu.

Vì vậy, mọi thứ dường như đang kiểm tra. Ngoại trừ phần tôi bị lỗi bộ nhớ. Tôi hoàn toàn có nhiều bộ nhớ hơn và tệp mà nó gặp phải là ~ 800KB, do đó, nó không thất bại khi đọc một tệp lớn.

Ngoài ra, tệp không bị hỏng. Tôi có thể đọc nó tốt, nếu tôi không sử dụng hết bộ nhớ trước đó.

Để làm cho mọi thứ trở nên khó hiểu hơn, tất cả điều này dường như hoạt động tốt trên máy Linux của tôi (mặc dù nó có bộ nhớ 16GB so với 8GB trên máy Windows của tôi), nhưng vẫn không có vẻ là RAM của máy đang gây ra sự cố này.

Tại sao Python ném lỗi bộ nhớ, khi tôi mong đợi rằng nó có thể phân bổ 2GB dữ liệu khác?

+0

Lượng RAM vật lý bạn có không liên quan. Trên Windows, bạn luôn có trao đổi, cho dù bạn có muốn hay không. – abarnert

+0

Khi điều này hoạt động trên máy linux của bạn ... đó là với một Python 32-bit là tốt? – abarnert

+1

bạn có thể đăng mã bạn đang sử dụng để tải tệp '.npz' không? nếu bạn sử dụng 'np.load (tập tin, mmap_mode = 'r +')' nó sẽ sử dụng ít bộ nhớ hơn, vì với đối số này bạn sẽ mở một ['mảng ánh xạ bộ nhớ'] (http://docs.scipy.org /doc/numpy/reference/generated/numpy.load.html) ... –

Trả lời

33

Tôi không biết lý do bạn cho rằng quy trình của bạn sẽ có thể truy cập 4GB. Theo số Memory Limits for Windows Releases tại MSDN, trên Windows 7 64 bit, quy trình 32 bit mặc định sẽ là 2GB. * Chính xác là nó đang chạy ở đâu.

Vì vậy, có cách nào đó không?

Vâng, bạn có thể tạo một bản dựng 32 bit tùy chỉnh sử dụng cờ IMAGE_FILE_LARGE_ADDRESS_AWARE và xây dựng lại numpy và tất cả các mô-đun mở rộng khác của bạn. Tôi không thể hứa rằng tất cả các mã có liên quan thực sự là an toàn để chạy với cờ nhận biết địa chỉ lớn; có một cơ hội tốt, nhưng trừ khi ai đó đã thực hiện nó và thử nghiệm nó, "một cơ hội tốt" là người tốt nhất có thể biết.

Hoặc, rõ ràng hơn, chỉ cần sử dụng Python 64 bit thay thế.


Lượng RAM vật lý hoàn toàn không liên quan. Dường như bạn nghĩ rằng bạn có giới hạn "8GB" với 8GB RAM, nhưng đó không phải là cách hoạt động của nó.Hệ thống của bạn chiếm tất cả RAM cộng với bất kỳ không gian hoán đổi nào cần thiết và chia nó giữa các ứng dụng; một ứng dụng có thể nhận được 20GB bộ nhớ ảo mà không bị lỗi bộ nhớ ngay cả trên máy 8GB. Và trong khi đó, một ứng dụng 32 bit không có cách nào truy cập nhiều hơn 4GB và hệ điều hành sẽ sử dụng một số không gian địa chỉ đó (một nửa theo mặc định, trên Windows), vì vậy bạn chỉ có thể nhận được 2GB ngay cả trên máy 8GB không chạy bất cứ thứ gì khác. (Không phải là nó có thể bao giờ là "không chạy bất cứ thứ gì" trên một hệ điều hành hiện đại, nhưng bạn biết những gì tôi có ý nghĩa.)


Vì vậy, tại sao không làm việc này trên hộp linux của bạn?

Vì hộp linux của bạn được định cấu hình để cung cấp quy trình 32 bit 3,5 GB không gian địa chỉ ảo, hoặc 3,99GB hoặc… Tôi không thể cho bạn biết số chính xác, nhưng mọi bản phân phối tôi đã thấy năm đã được cấu hình ít nhất 3.25GB.


* Cũng lưu ý rằng bạn thậm chí không thực sự nhận được 2GB đầy đủ cho dữ liệu của mình; chương trình của bạn. Hầu hết những gì hệ điều hành và trình điều khiển của nó có thể truy cập vào mã của bạn nằm trong nửa kia, nhưng một số bit nằm trong nửa của bạn, cùng với mọi DLL bạn tải và bất kỳ không gian nào họ cần và nhiều thứ khác. Nó không thêm quá nhiều, nhưng nó không phải là số không.

+0

Bạn thực sự không phải biên dịch exe trên các cửa sổ, 'IMAGE_FILE_LARGE_ADDRESS_AWARE' chỉ là một lá cờ trong tiêu đề hình ảnh (không phải điều này sẽ được hỗ trợ chính thức nhưng chúng tôi không phán xét;)). Ngoài ra dlls không có tiếng nói trong vấn đề để bắt đầu, vì vậy những người không phải được thay đổi dù sao đi nữa. – Voo

+0

@Voo: Nhưng tất cả mã của bạn, kể cả các tệp DLL của bạn, phải an toàn để sử dụng _use_ cùng với cờ. Nếu nói, Python và các mô-đun mở rộng tiêu chuẩn của nó kiểm tra tại thời gian xây dựng cho dù bạn muốn hỗ trợ nhận biết địa chỉ lớn và tạo mã khác nhau trong các trường hợp khác nhau, bạn sẽ cần phải xây dựng lại mọi thứ, chứ không phải chỉ exe. Nếu chúng là _always_ địa chỉ an toàn lớn, thì bạn không cần phải làm gì cả. Và nếu chúng _never_ địa chỉ an toàn lớn, thì việc xây dựng lại sẽ không giúp ích gì. Tôi không biết bất kỳ tài liệu nào cho bạn biết cái nào trong số đó là… – abarnert

+0

Đúng, mặc dù lý do duy nhất mã sẽ thất bại với IMAGE_FILE_LARGE_ADDRESS_AWARE là nếu nó bị hỏng để bắt đầu (toán con trỏ đã ký) hoặc thực hiện các thủ thuật ngu ngốc với bit thứ tự cao của con trỏ. Tôi rất ngạc nhiên khi python thực hiện công cụ này - ở đâu chính xác trong mã? (GC tôi giả định, nó là khá nhiều lý do duy nhất mà điều này có thể hữu ích) Rất thích nhìn vào đó. – Voo

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