2014-11-05 17 views
10

Tôi đang cố gắng sử dụng các ma trận vuông rất lớn trong Java, theo thứ tự n = 1e6 hoặc nhiều hơn. Các ma trận không phải là thưa thớt, vì vậy tôi không thấy nhiều cách xung quanh đại diện cho họ như là một mảng 2D, mà đòi hỏi n^2 * sizeof (int) bit của bộ nhớ. Rõ ràng, tôi đang nhận được lỗi tràn bộ nhớ heap, ngay cả khi thêm cờ trình biên dịch để sử dụng như một đống lớn như máy tính của tôi sẽ cho phép.Tối đa hóa không gian Java Heap

Tôi sẵn sàng giả sử tôi có máy tính hoàn hảo (RAM không giới hạn, v.v.) vì lợi ích của câu hỏi, mặc dù trên thực tế tôi đang sử dụng máy 64 bit với 16 hợp RAM. Dường như máy của tôi chỉ có liên quan, vì tôi bị giới hạn bởi JVM chứ không phải phần cứng thực của tôi (trong đó JVM không thể có bộ nhớ nhiều hơn so với máy vật lý của tôi).

Tôi hiểu (và được trích dẫn, ví dụ: tại đây Making a very large Java array) rằng một mảng Java không thể, thậm chí về mặt lý thuyết, lớn hơn MAX_INT như được sử dụng để lập chỉ mục.

Câu hỏi của tôi là: là có cách nào để dỗ thêm bộ nhớ ra khỏi đống JVM

Tôi hiểu rằng, nếu có, họ có thể sẽ không làm cho tôi một thông tin độ lớn hơn.

Ví dụ

Trong C, tôi có thể khai báo các biến liên tục tĩnh và họ đã chuyển đến phần dữ liệu của mã đó sẽ có không gian nhiều hơn so với đống và nhiều nhiều hơn chồng (Where are static variables stored (in C/C++)?).

Trong Java, có vẻ như ngay cả khi tôi sao chép biến vào phần "dữ liệu", giá trị sẽ đi vào heap chính static allocation in java - heap, stack and permanent generation có nghĩa là tôi đã thành công trong việc di chuyển toàn bộ byte ra khỏi heap (yay !)

giải pháp của tôi

của tôi "giải pháp" không phải là thực sự là một giải pháp. Tôi đã tạo một cấu trúc dữ liệu đơn giản để sử dụng các thủ tục iF RandomFileAccess để thay thế các truy cập mảng bằng cách đọc và ghi vào một tệp bên ngoài. Nó vẫn là truy cập thời gian không đổi, nhưng chúng tôi đã đi từ một trong những hoạt động nhanh nhất của Java đến một thủ tục rất chậm (mặc dù chúng ta có thể kéo các dòng "cache" từ tập tin cùng một lúc, điều này làm cho quá trình này cực kỳ nhanh hơn). Ý tưởng tốt hơn?

Không My Câu hỏi

Tôi không yêu cầu làm thế nào để làm cho một mảng trên kích thước mảng tối đa của java. Điều đó là không thể. Đây là các mảng lồng nhau - một mảng có kích thước n duy nhất là tốt, n trong số chúng gây ra vấn đề.

Tôi không yêu cầu điều này How to deal with "java.lang.OutOfMemoryError: Java heap space" error (64MB heap size). Bộ sưu tập rác không có liên quan - tôi thậm chí không thể làm cho các mảng cho phép một mình lo lắng về khi nó bị xóa.

Tôi cũng không thể sử dụng trình lặp (tôi nghĩ), nếu không sẽ là một khả năng; một hàm như phép nhân ma trận cần có thể trực tiếp lập chỉ mục

Lưu ý: Java không phải là ngôn ngữ phù hợp để thực hiện các phép toán trên các ma trận rất lớn. Tôi nên sử dụng bàn tính tốt hơn. Nhưng tôi ở đây và ngoài tầm kiểm soát của tôi.

+0

bạn có thể phân phối tính toán trong nhiều JVM không? sử dụng một cái gì đó như JPPF, [ở đây] (http://www.jppf.org/samples-pack/MatrixMultiplication/Readme.php) là một ví dụ –

+0

Nó có hoạt động để chỉ phân bổ nhiều ram khi bạn chạy không? – JClassic

+0

@jigar Không biết, nhìn vào nó ngay bây giờ! –

Trả lời

3

Có một số khía cạnh còn thiếu đối với câu hỏi ban đầu của bạn; ví dụ, tôi không thể tin rằng bạn phải sử dụng các ma trận lớn như vậy và chỉ "quên chúng" giữa các lần chạy. Vâng, có thể bạn làm, tôi không biết.

Dù sao: việc bạn sử dụng RandomAccessFile là, imho, gần đó; chỉ rằng nếu tôi là bạn, tôi sẽ sử dụng FileChannel.map(). Trên các hệ thống Unix, về cơ bản nó là một cách để gọi mmap(2). Trong kịch bản dưới đây, tôi giả định rằng bạn có một FileChannel cho ma trận của bạn (tôi lấy nó, bạn hiểu những gì tôi có ý nghĩa).

Vì bạn sử dụng ma trận, vì có vẻ như giá trị tại bất kỳ "tọa độ" nào trong ma trận đều có cùng độ dài, có nghĩa là bạn có thể dễ dàng tính toán bù trừ vào tệp để đọc và/hoặc ghi giá trị vào ma trận. Tất nhiên, bạn sẽ không muốn ánh xạ giá trị, nhưng một cửa sổ chứa giá trị đó; làm cho cửa sổ đủ lớn để có ích, và đừng lo lắng về mức tiêu thụ không gian heap: FileChannel.map() không tiêu thụ không gian heap (lưu cho sổ kế toán đối tượng). Trên các JVM 64 bit, bạn không cần lo lắng; bạn đã sử dụng một JVM 32 bit chưa, bạn phải tính đến tình trạng cạn kiệt không gian địa chỉ.

Có, tất nhiên, vấn đề hết hạn: bạn cần bản đồ này hoặc bản đồ đó để hoạt động trong bao lâu. Điều này là hoàn toàn phụ thuộc vào chương trình của bạn và những gì bạn làm với nó. Nhưng sử dụng FileChannel và lập bản đồ các khu có liên quan là con đường để đi. Tuy nhiên, bạn nên nhớ rằng không an toàn để lập bản đồ nhiều hơn 2^31 - 1 byte; giải quyết cho 2^30 (1 GiB) cửa sổ byte, ví dụ; và nhắc nhở rằng bạn có thể chuyển đổi ByteBuffer s thành IntBuffer s.


Chỉnh sửa: một số liên kết có liên quan:

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