2012-11-26 12 views
6

Có thể lặp qua một tệp văn bản trên một máy đa lõi song song với R không? Đối với ngữ cảnh, tệp văn bản nằm trong khoảng từ 250-400MB đầu ra JSON.Có thể readLines được thực hiện song song trong R

CHỈNH SỬA:

Dưới đây là một số mẫu mã mà tôi đang chơi cùng. Trước sự ngạc nhiên của tôi, việc xử lý song song đã không giành chiến thắng - chỉ cơ bản lapply - nhưng điều này có thể là do lỗi người dùng trên một phần của tôi. Ngoài ra, khi cố đọc một số tệp lớn, máy của tôi bị nghẹt thở.

## test on first 100 rows of 1 twitter file 
library(rjson) 
library(parallel) 
library(foreach) 
library(plyr) 
N = 100 
library(rbenchmark) 
mc.cores <- detectCores() 
benchmark(lapply(readLines(FILE, n=N, warn=FALSE), fromJSON), 
      llply(readLines(FILE, n=N, warn=FALSE), fromJSON), 
      mclapply(readLines(FILE, n=N, warn=FALSE), fromJSON), 
      mclapply(readLines(FILE, n=N, warn=FALSE), fromJSON, 
        mc.cores=mc.cores), 
      foreach(x=readLines(FILE, n=N, warn=FALSE)) %do% fromJSON(x), 
      replications=100) 

Đây là một mẫu mã thứ hai

parseData <- function(x) { 
    x <- tryCatch(fromJSON(x), 
       error=function(e) return(list()) 
       ) 
    ## need to do a test to see if valid data, if so ,save out the files 
    if (!is.null(x$id_str)) { 
    x$created_at <- strptime(x$created_at,"%a %b %e %H:%M:%S %z %Y") 
    fname <- paste("rdata/", 
        format(x$created_at, "%m"), 
        format(x$created_at, "%d"), 
        format(x$created_at, "%Y"), 
        "_", 
        x$id_str, 
        sep="") 
    saveRDS(x, fname) 
    rm(x, fname) 
    gc(verbose=FALSE) 
    } 
} 

t3 <- system.time(lapply(readLines(FILES[1], n=-1, warn=FALSE), parseData)) 
+0

Có phải vấn đề khi đọc tệp JSON hoặc phân tích cú pháp tệp JSON không? –

+0

Không. Máy của tôi cuối cùng bị đóng băng khi tôi cố gắng sử dụng một vòng lặp đơn giản. Tôi đã cố gắng chạy một hàm chống lại mỗi mục nhập JSON, lưu các tệp rds riêng biệt để đọc lại, v.v. v.v. Với mọi tùy chọn, tôi cũng ý thức được việc sử dụng bộ nhớ và cố gắng tối ưu hóa và làm sạch khi có thể. Một số ý tưởng là khủng khiếp, nhưng cuối cùng, tôi muốn tìm ra cách để "phân tích" tập dữ liệu lớn hơn chỉ với Base R, bỏ qua thực tế là các giải pháp tốt hơn tồn tại trong thời điểm này. – Btibert3

+0

Ví dụ có thể tái sản xuất sẽ giúp chúng tôi cung cấp phản hồi dễ dàng hơn nhiều. –

Trả lời

7

Câu trả lời phụ thuộc vào những gì vấn đề thực sự là: đọc tệp song song hoặc xử lý tệp song song.

Đọc song song

Bạn có thể chia tệp JSON thành nhiều tệp đầu vào và đọc chúng song song, ví dụ: bằng cách sử dụng chức năng plyr kết hợp với một phụ trợ song song:

result = ldply(list.files(pattern = ".json"), readJSON, .parallel = TRUE) 

Đăng ký một backend có lẽ có thể được thực hiện bằng cách sử dụng gói parallel mà hiện nay được tích hợp trong cơ sở R. Hoặc bạn có thể sử dụng gói doSNOW, xem this post on my blog để biết chi tiết.

chế biến song song

Trong kịch bản này đặt cược tốt nhất của bạn là để đọc toàn bộ tập dữ liệu vào một vector của các nhân vật, chia các dữ liệu và sau đó sử dụng một backend song song kết hợp với ví dụ các chức năng plyr.

+1

Không phải là một ý tưởng tồi. Và nếu bạn đang tìm kiếm một cách để cắt tập tin, hãy xem lệnh UNIX 'split'. –

+0

Lệnh Linux luôn là giải pháp tốt;) –

+0

@JeffAllen Thú vị.Đã không thực sự nghĩ trước khi xử lý dữ liệu trước khi có lệnh. Không phải là một chuyên gia ở dòng lệnh bởi bất kỳ căng, nhưng tôi càng poke xung quanh, tôi thấy như thế nào mạnh mẽ một vài lệnh có thể được. – Btibert3

2

lẽ không phải với readLines() do bản chất của không song song tập tin hệ thống IO. Tất nhiên, nếu bạn đang sử dụng một NFS song song hoặc một cái gì đó giống như HDFS, thì hạn chế này sẽ không áp dụng. Nhưng giả sử bạn đang sử dụng kiến ​​trúc "chuẩn", bạn sẽ không thể thực hiện song song các cuộc gọi readLine() của mình.

Tốt nhất có lẽ sẽ là để đọc trong toàn bộ tập tin khi nhìn thấy như < 500MB lẽ sẽ phù hợp trong bộ nhớ, sau đó parallelize chế biến khi bạn đang đối tượng đã được đọc trong.

+0

+1, nhưng với một chút công việc bạn có thể có thể nhận được song song 'readLines' bằng cách gán số dòng cho mỗi công nhân mà họ cần đọc từ một kết nối tệp đã cho. –

+0

@PaulHiemstra bạn có thể đưa ra ví dụ về cách thực hiện điều đó trong trường hợp đơn giản nhất có thể không? :) –

+0

@AnthonyDamico Tôi không có thời gian ngay bây giờ, nhưng tôi nghĩ rằng nó không phải là tầm thường, và nó rất tốt có thể không hoạt động. –