Как создать индикатор выполнения для загрузки данных в R? - PullRequest
23 голосов
/ 29 мая 2011

Можно ли создать индикатор выполнения для данных, загруженных в R, используя load () ?

Для проекта анализа данных в R загружаются большие матрицы из файлов .RData, загрузка которых занимает несколько минут. Я хотел бы иметь индикатор выполнения, чтобы отслеживать, сколько времени пройдет, прежде чем данные будут загружены. В R уже встроена хорошая индикатор выполнения , но load () не имеет хуков для отслеживания объема прочитанных данных. Если я не могу использовать нагрузку напрямую, есть ли косвенный способ создать такой индикатор? Возможно, загрузив файл .RData в патроны и собрав их вместе для R. Есть ли у кого-нибудь какие-либо мысли или предложения по этому поводу?

Ответы [ 2 ]

12 голосов
/ 10 июня 2011

Я пришел к следующему решению, которое будет работать для файлов размером менее 2 ^ 32 - 1 байт.

Объект R необходимо сериализовать и сохранить в файл, как показано в следующем коде.

saveObj <- function(object, file.name){
    outfile <- file(file.name, "wb")
    serialize(object, outfile)
    close(outfile)
}

Затем мы читаем двоичные данные кусками, отслеживая, сколько этосоответственно прочитайте и обновите индикатор выполнения.

loadObj <- function(file.name){
    library(foreach)
    filesize <- file.info(file.name)$size
    chunksize <- ceiling(filesize / 100)
    pb <- txtProgressBar(min = 0, max = 100, style=3)
    infile <- file(file.name, "rb")
    data <- foreach(it = icount(100), .combine = c) %do% {
        setTxtProgressBar(pb, it)
        readBin(infile, "raw", chunksize)
    }
    close(infile)
    close(pb)
    return(unserialize(data))
}

Код можно запустить следующим образом:

> a <- 1:100000000
> saveObj(a, "temp.RData")
> b <- loadObj("temp.RData")
  |======================================================================| 100%
> all.equal(b, a)
[1] TRUE

Если мы сравниваем метод индикатора выполнения с чтением файла в одном фрагменте, мыувидеть, что индикатор выполнения немного медленнее, но его недостаточно для беспокойства.

> system.time(unserialize(readBin(infile, "raw", file.info("temp.RData")$size)))
   user  system elapsed
  2.710   0.340   3.062
> system.time(b <- loadObj("temp.RData"))
  |======================================================================| 100%
   user  system elapsed
  3.750   0.400   4.154

Так что, хотя вышеуказанный метод работает, я чувствую, что он совершенно бесполезен из-за ограничений размера файла.Индикаторы выполнения полезны только для больших файлов, чтение которых занимает много времени.

Было бы замечательно, если бы кто-то смог придумать что-то лучше, чем это решение!

3 голосов
/ 15 июня 2011

Могу ли я вместо этого предложить ускорить загрузку (и сохранить), чтобы индикатор выполнения не требовался?Если чтение одной матрицы «быстрое», вы можете сообщить о прогрессе между каждой матрицей чтения (если у вас их много).

Вот некоторые измерения.Просто установив compress = FALSE, скорость загрузки удваивается.Но при написании простого матричного сериализатора скорость загрузки почти в 20 раз выше.

x <- matrix(runif(1e7), 1e5) # Matrix with 100k rows and 100 columns

system.time( save('x', file='c:/foo.bin') ) # 13.26 seconds
system.time( load(file='c:/foo.bin') ) # 2.03 seconds

system.time( save('x', file='c:/foo.bin', compress=FALSE) ) # 0.86 seconds
system.time( load(file='c:/foo.bin') ) # 0.92 seconds

system.time( saveMatrix(x, 'c:/foo.bin') ) # 0.70 seconds
system.time( y <- loadMatrix('c:/foo.bin') ) # 0.11 seconds !!!
identical(x,y)

Где saveMatrix / loadMatrix определены следующим образом.В настоящее время они не обрабатывают dimnames и другие атрибуты, но их можно легко добавить.

saveMatrix <- function(m, fileName) {
    con <- file(fileName, 'wb')
    on.exit(close(con))
    writeBin(dim(m), con)
    writeBin(typeof(m), con)
    writeBin(c(m), con)
}

loadMatrix <- function(fileName) {
    con <- file(fileName, 'rb')
    on.exit(close(con))
    d <- readBin(con, 'integer', 2)
    type <- readBin(con, 'character', 1)
    structure(readBin(con, type, prod(d)), dim=d)
}
...