Импорт очень большого набора данных в h2o из sqlite - PullRequest
1 голос
/ 26 апреля 2020

У меня есть база данных около 500G. Он состоит из 16 таблиц, каждая из которых содержит 2 или 3 столбца (первый столбец может быть отброшен) и 1 375 328 760 строк. Мне нужно, чтобы все таблицы были объединены в один кадр данных в H2O, поскольку они необходимы для выполнения прогноза в модели XGB. Я попытался преобразовать отдельные таблицы sql в среду h2o, используя as.h2o, и h2o.cbind их 2 или 3 таблицы одновременно, пока они не станут одним набором данных. Тем не менее, я получаю это «G C превышен предел накладных расходов: java .lang.OutOfMemoryError», после преобразования 4 таблиц. Есть ли способ обойти это? Мои технические характеристики машины составляют 124 ГБ ОЗУ, ОС (Rhel 7,8), Root (1 ТБ), Home (600 ГБ) и 2 ТБ внешнего жесткого диска. Модель запускается на этом локальном компьютере, а max_mem_size установлен на 100G. Подробности кода приведены ниже.

library(data.table)
library(h2o)          
h2o.init(
  nthreads=14,          
  max_mem_size = "100G")    
h2o.removeAll() 

setwd("/home/stan/Documents/LUR/era_aq")

l1.hex <- as.h2o(d2)
l2.hex <- as.h2o(lai)
test_l1.hex <-h2o.cbind(l1.hex,l2.hex[,-1])
h2o.rm (l1.hex,l2.hex)
l3.hex <- as.h2o(lu100)
l4.hex <- as.h2o(lu1000)
test_l2.hex <-h2o.cbind(l3.hex,l4.hex[,-1])
h2o.rm(l3.hex,l4.hex)
l5.hex <- as.h2o(lu1250)
l6.hex <- as.h2o(lu250)
test_l3.hex <-h2o.cbind(l5.hex,l6.hex[,-1])
h2o.rm(l5.hex,l6.hex)
l7.hex <- as.h2o(pbl)
l8.hex <- as.h2o(msl)
test_l4.hex <-h2o.cbind(l7.hex,l8.hex[,-1])
h2o.rm(ll7.hex,l8.hex)

test.hex <-h2o.cbind(test_l1.hex,test_l2.hex[,-1],test_l3.hex[,-1],test_l4.hex[,-1])
test <- test.hex[,-1]
test[1:3,]```

Ответы [ 2 ]

2 голосов
/ 26 апреля 2020

Во-первых, как сказал Том в комментариях, вам понадобится лодка побольше. H2O хранит все данные в памяти, и, как правило, вам нужно в 3-4 раза больше данных, чтобы иметь возможность делать с ними что-нибудь полезное. Набор данных объемом 500 ГБ означает, что вам нужно, чтобы общая память вашего кластера составляла 1,5-2 ТБ.

(H2O хранит сжатые данные, и я не думаю, что это делает sqlite, и в этом случае вам может сойти только требуется 1 ТБ.)

Во-вторых, as.h2o() - это неэффективный способ загрузки больших наборов данных. Что произойдет, если ваш набор данных будет загружен в область памяти R, затем он будет сохранен в файл CSV, затем этот файл CSV будет передан по TCP / IP в процесс H2O.

Итак, лучший способ состоит в том, чтобы экспорт напрямую из sqlite в файл csv. А затем используйте h2o.importFile() для загрузки этого CSV-файла в H2O.

h2o.cbind() также потребует большого количества копий. Если вы сможете найти инструмент или скрипт для привязки столбцов csv-файлов перед импортом, это может быть более эффективным. Был найден быстрый поиск csvkit , но я не уверен, нужно ли ему загружать файлы в память или можно полностью работать с файлами на диске.

1 голос
/ 26 апреля 2020

Поскольку память является премиальной и все R работают в ОЗУ, избегайте хранения больших вспомогательных объектов data.table и h20 в вашей глобальной среде. Подумайте о настройке функции для создания списка для компиляции, когда временные объекты удаляются, когда функция выходит за рамки. В идеале вы должны создавать свои h2o объекты непосредственно из источника файла:

# BUILD LIST OF H20 OBJECTS WITHOUT HELPER COPIES
h2o_list <- lapply(list_of_files, function(f) as.h2o(data.table::fread(f))[-1])
# h2o_list <- lapply(list_of_files, function(f) h2o.importFile(f)[-1])

# CBIND ALL H20 OBJECTS
test.h2o <- do.call(h2o.cbind, h2o_list)

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

build_h2o <- function(f) as.h2o(data.table::fread(f))[-1])
# build_h2o <- function(f) h2o.importFile(f)[-1]

test.h2o <- do.call(h2o.cbind, lapply(list_of_files, build_h2o))

Расширьте функцию с if для некоторых наборов данных, которые должны сохранять первый столбец или нет.

build_h2o <- function(f) {
   if (grepl("lai|lu1000|lu250|msl", f)) { tmp <- fread(f)[-1] }
   else { tmp <- fread(f) }

   return(as.h2o(tmp))
}

Наконец, если возможно, используйте data.table методы, такие как cbindlist :

final_dt <- cbindlist(lapply(list_of_files, function(f) fread(f)[-1]))

test.h2o <- as.h2o(final_dt)

rm(final_dt)
gc()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...