2012-04-30 52 views
20

Tôi có một tệp văn bản rất lớn (+ 10GB) mà tôi muốn đọc cho một số kỹ thuật khai thác dữ liệu. Để làm điều đó, tôi sử dụng kỹ thuật song song với MPI vì vậy nhiều quá trình có thể truy cập cùng nhau vào cùng một tệp.
Thực tế, tôi muốn mỗi quá trình đọc N số dòng. Vì tệp không được cấu trúc (cùng số trường nhưng mỗi trường có thể chứa số ký tự khác nhau), tôi có nghĩa vụ phân tích cú pháp tệp và điều đó không song song và phải mất rất nhiều thời gian. Có cách nào để truy cập trực tiếp vào một số dòng cụ thể với tính năng phân tích cú pháp và đếm các dòng không? Cảm ơn sự giúp đỡ của bạn.Cách truy cập trực tiếp và hiệu quả vào tệp văn bản rất lớn?

Trả lời

21

Nếu tệp của bạn không được lập chỉ mục khác, không có cách nào trực tiếp.

Lập chỉ mục có thể đáng giá (quét tìm một lần để tìm tất cả các kết thúc dòng và lưu trữ bù của mỗi dòng hoặc đoạn đường). Nếu bạn cần xử lý tệp nhiều lần và không thay đổi, chi phí lập chỉ mục có thể được bù đắp bằng cách sử dụng chỉ mục để chạy tiếp.

Nếu không, nếu bạn không cần tất cả các công việc để có chính xác cùng một số dòng/mục, bạn chỉ có thể giả mạo nó.
Tìm kiếm một giá trị đã cho (ví dụ 1G) và tìm dấu tách dòng gần nhất. Lặp lại tại offset 2G, vv cho đến khi bạn đã tìm thấy đủ điểm break.

Sau đó, bạn có thể kích hoạt các tác vụ song song của mình trên từng khối bạn đã xác định.

+0

Cảm ơn bạn đã trả lời. tôi nghĩ rằng ý tưởng thứ hai là tốt hơn vì tôi thường phân tích cú pháp tệp đúng lúc. Vì vậy, xem xét soluion này, tôi sẽ làm cho mỗi quá trình truy cập từ một bù đắp cụ thể cho phép nói (File_size/process_number * process_rank) sau đó tôi tìm sự bắt đầu của một dòng mới. Vì vậy, tôi sẽ lỏng lẻo ở dòng number_of_process tồi tệ hơn? – ezzakrem

+0

+1 Quét một lần để tìm các ngắt dòng và chuyển các chỉ mục sang các quy trình khác hoàn toàn thích hợp hơn với bất kỳ điều gì khác, bởi vì bất kỳ tìm kiếm ngẫu nhiên nào cũng sẽ có nhiều đơn đặt hàng đắt hơn bất kỳ thứ gì bạn có thể mua từ việc phân tích cú pháp của một số trường trên mỗi dòng một tệp văn bản. Tuần tự đọc và kéo từ bộ nhớ cache đệm nhanh, mọi thứ khác đều đánh bại mọi tối ưu hóa. – Damon

+0

@ezzakrem: nếu bạn có thể không đủ khả năng phân tích các dòng nhất định, tôi đoán bạn có thể làm điều đó. Nhưng tôi sẽ không. Trước khi bạn bắt đầu sinh ra công nhân, trong "chủ đề" chính của bạn, bạn sẽ tìm thấy tất cả các điểm vỡ mà bạn cần. Bạn bắt đầu/kết thúc offsets cho mỗi người lao động trước khi bạn bắt đầu. – Mat

4

Không có không: cho đến khi bạn không đọc qua dữ liệu không xác định của bạn, không ai biết có bao nhiêu ký tự dòng mới. Độ phức tạp của vấn đề này là O (n) do đó có nghĩa là ít nhất một lần là bạn sẽ phải đọc toàn bộ tệp. Sau đó, bạn có thể muốn xây dựng một bảng chỉ mục nơi bạn ghi lại nơi có các ký tự dòng mới trong tệp của bạn: điều này có thể được sử dụng bởi tất cả quy trình và với fseek bạn có thể tăng tốc truy cập đáng kể hơn nữa.

+0

cảm ơn bạn đã trả lời, có vẻ như là một giải pháp tốt. Tôi sẽ làm điều đó và xem nếu nó có giá trị kể từ trong chế độ nối tiếp, tôi đọc một tập tin, sau đó cho mỗi dòng tôi làm nhiều tính toán CPU. Cho đến nay tôi có hai giải pháp: tôi phân tích cú pháp tập tin để xây dựng một tập tin chỉ mục sau đó tất cả các quá trình có thể sử dụng nó. Hoặc tôi làm cho một quá trình đọc từ tập tin và làm cho các quá trình khác làm tính toán. – ezzakrem

+0

Với O (n) tôi đã gọi ký hiệu này: http://en.wikipedia.org/wiki/Time_complexity#Linear_time Bằng cách này, việc lập chỉ mục rất dễ thực hiện song song. Nếu bạn có nhiều quy trình, bạn có thể chia nhỏ tệp _also để lập chỉ mục_, vì vậy, hãy nói quy trình thứ nhất đọc qua Gb đầu tiên, thứ 2, v.v ... và lưu tất cả các vị trí của các ký tự dòng mới vào cùng một tài nguyên được chia sẻ . Điều này cũng có thể tăng tốc độ lập chỉ mục. Tuy nhiên, đừng quên rằng tùy thuộc vào phần cứng lưu trữ bạn sử dụng, việc đọc tuần tự có thể nhanh hơn MUCH. – MrTJ

+0

do đó, về việc trộn hai bước 1- làm cho các quy trình N nhận chỉ mục như bạn đã nói. 2- đối với tính toán cpu, mỗi quá trình truy cập trực tiếp với fseek() để bù trừ cụ thể. Điều đó có vẻ tốt đẹp để thử. Cảm ơn bạn – ezzakrem

10

Một vài lựa chọn khác ngoài những gì đã được đề cập ở đây rằng sẽ không yêu cầu quét toàn bộ file:

  1. làm cho một quá trình tổng thể đẩy dòng qua ống/FIFOs để tiến trình con mà làm việc xử lý thực tế. Điều này có thể là một chút chậm hơn nhưng nếu nói 90% thời gian dành cho các quy trình con là việc crunching văn bản thực tế, nó sẽ ổn.

  2. Bí quyết ngu ngốc nhưng hiệu quả: giả sử bạn có N quy trình và bạn có thể nói với từng quá trình bằng argv hoặc một số "số sê-ri", ví dụ: processor -serial_number [1|2|3...N] -num_procs N, tất cả chúng đều có thể đọc cùng một dữ liệu nhưng chỉ xử lý các dòng có lineno % num_procs == serial_number. nó kém hiệu quả hơn một chút bởi vì tất cả chúng sẽ đọc toàn bộ dữ liệu, nhưng một lần nữa, nếu chúng chỉ hoạt động trên mọi dòng Nth, và đó là những gì tiêu thụ phần lớn thời gian, bạn sẽ ổn thôi.

+1

+1 cho tư duy thay thế. Đôi khi cách tốt nhất để giành chiến thắng, là thay đổi các quy tắc. –

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