Dưới đây là một ý tưởng:
Bạn nói rằng bạn có một ma trận rách rưới, tức là một danh sách liệt kê có độ dài khác nhau . Tôi giả sử số điểm nổi.
Bạn có thể làm phẳng ma trận để nhận được một ô được đóng gói 1D (sử dụng Developer`ToPackedArray
để đóng gói nếu cần) và lưu trữ chỉ mục bắt đầu của danh sách phụ riêng biệt. Sau đó, xây dựng lại ma trận rách rưới sau khi dữ liệu đã được nhập.
Đây là một minh chứng trong Mathematica (tức là sau khi nhập), việc trích xuất các danh sách con từ danh sách phẳng được làm phẳng nhanh.
data = RandomReal[1, 10000000];
indexes = [email protected][{1, 10000000}, 10000];
ranges = #1 ;; (#2 - 1) & @@@ Partition[indexes, 2, 1];
data[[#]] & /@ ranges; // Timing
{0.093, Null}
Hoặc lưu trữ chuỗi độ dài danh sách phụ và sử dụng Mr.Wizard's dynamicPartition
function thực hiện chính xác điều này. Quan điểm của tôi là lưu trữ dữ liệu theo định dạng phẳng và phân vùng dữ liệu trong hạt nhân sẽ thêm chi phí không đáng kể.
Nhập các mảng được đóng gói dưới dạng tệp MX rất nhanh. Tôi chỉ có 2 GB bộ nhớ, vì vậy tôi không thể thử nghiệm trên các tệp rất lớn, nhưng thời gian nhập luôn luôn là một phần nhỏ của một giây cho các mảng được đóng gói trên máy của tôi. Điều này sẽ giải quyết được vấn đề rằng việc nhập dữ liệu không được đóng gói có thể chậm hơn (mặc dù như tôi đã nói trong các nhận xét về câu hỏi chính, tôi không thể tái tạo loại chậm nhất mà bạn đề cập đến).
Nếu BinaryReadList
đã nhanh (nó không phải là nhanh như đọc file MX bây giờ, nhưng có vẻ như it will be significantly sped up in Mathematica 9), bạn có thể lưu trữ toàn bộ dữ liệu là một tập tin nhị phân lớn, mà không cần phải phá vỡ nó thành các tệp MX riêng biệt. Sau đó, bạn có thể nhập khẩu phần có liên quan của tập tin như thế này:
Đầu tiên tạo một tập tin thử nghiệm:
In[3]:= f = OpenWrite["test.bin", BinaryFormat -> True]
In[4]:= BinaryWrite[f, RandomReal[1, 80000000], "Real64"]; // Timing
Out[4]= {9.547, Null}
In[5]:= Close[f]
mở nó:
In[6]:= f = OpenRead["test.bin", BinaryFormat -> True]
In[7]:= StreamPosition[f]
Out[7]= 0
Bỏ qua 5 triệu mục đầu tiên:
In[8]:= SetStreamPosition[f, 5000000*8]
Out[8]= 40000000
Đọc 5 triệu mục nhập:
In[9]:= BinaryReadList[f, "Real64", 5000000] // Length // Timing
Out[9]= {0.609, 5000000}
đã đọc tất cả các mục còn lại:
In[10]:= BinaryReadList[f, "Real64"] // Length // Timing
Out[10]= {7.782, 70000000}
In[11]:= Close[f]
(Để so sánh, Get
thường đọc cùng một dữ liệu từ một file MX trong vòng chưa đầy 1,5 giây ở đây. Tôi đang trên WinXP btw.)
EDIT Nếu bạn sẵn sàng dành thời gian về vấn đề này, và viết một số mã C, ý tưởng khác là để tạo một hàm thư viện (sử dụng Library Link) mà sẽ nhớ bản đồ tệp (link for Windows) và sao chép trực tiếp vào đối tượng MTensor
(một MTensor
chỉ là một mảng Mathematica được đóng gói, như được thấy từ phía C của Liên kết Thư viện).
[Trợ giúp này] (http://stackoverflow.com/q/7525782/616736)? Một [câu hỏi có liên quan] khác (http://stackoverflow.com/q/8247005/616736). – abcd
@yoda Lưu ý rằng Rolf đang sử dụng MX là định dạng nhị phân nguyên gốc của Mathematica, và trong exeprience của tôi nhanh hơn bất cứ điều gì khác khi sử dụng 'Import' /' ReadList'. Tôi không biết về 'BinaryReadList' ... – Szabolcs
@Rolf ** + 1 **, câu hỏi rất phù hợp. Nó không trả lời bạn, nhưng bạn chắc chắn sẽ quan tâm [trong bài thuyết trình này] (http://library.wolfram.com/infocenter/Conferences/8025/). Có vẻ như Mathematica 9 đang mang lại những cải tiến đáng kể trong lĩnh vực này. – Szabolcs