#r #multicore
#r #многоядерный
Вопрос:
Я продолжаю сталкиваться с проблемой с multicore
пакетом и большими объектами. Основная идея заключается в том, что я использую функцию Bioconductor ( readBamGappedAlignments
) для чтения в больших объектах. У меня есть символьный вектор имен файлов, и я использовал mclapply
для перебора файлов и считывания их в список. Функция выглядит примерно так:
objects <- mclapply(files, function(x) {
on.exit(message(sprintf("Completed: %s", x)))
message(sprintf("Started: '%s'", x))
readBamGappedAlignments(x)
}, mc.cores=10)
Однако я продолжаю получать следующую ошибку: Error: serialization is too large to store in a raw vector
. Однако, кажется, я могу читать одни и те же файлы в одиночку без этой ошибки. Я нашел упоминание об этой проблеме здесь, без разрешения.
Приветствуются любые предложения по параллельному решению — это должно выполняться параллельно. Я мог бы обратить внимание на snow, но у меня есть очень мощный сервер с 15 процессорами, по 8 ядер на каждом и 256 ГБ памяти, на которых я могу это сделать. Я предпочитаю просто делать это на этой машине по ядрам, а не использовать один из наших кластеров.
Комментарии:
1. Вы можете использовать кластеры сокетов со snow на одной машине (по умолчанию используется ‘localhost’).
2. Ошибка возникает из-за того, что данные преобразуются в вектор типа raw, когда родительский элемент пытается извлечь данные из дочернего элемента, а вектор длиннее самого длинного вектора R 2 ^ 31 — 1. Попробуйте перенести больше работы внутрь функции, чтобы результатом было «сокращение» больших данных.
3. Огромное спасибо, Мартин! Я подозревал, что это может быть связано с этим, но думал, что это проявится в другом сообщении об ошибке. Отсутствие использования
R_len_t
снова поднимает уродливую голову… было бы здорово, если бы мы могли просто установить для этого значение long и покончить с этим.4. Вместо этого вы могли бы переключиться на использование
foreach
, хотя я не совсем понимаю, где встречается длинный вектор. Если ничего другого, вы также могли бы разделить объекты таким образом, чтобы отобразить длинный вектор в матрицу, разделив каждый, скажем, 2 ^ 30 элементов в новый столбец.5. можете ли вы отследить ошибку, чтобы мы могли узнать точное место ее возникновения?
Ответ №1:
По слухам, ограничение на целое число будет устранено очень скоро в R. По моему опыту, это ограничение может блокировать наборы данных, содержащие менее 2 миллиардов ячеек (около максимального целого числа), а низкоуровневые функции, такие как sendMaster
в multicore
пакете, полагаются на передачу необработанных векторов. У меня было около 1 миллиона процессов, представляющих около 400 миллионов строк данных и 800 миллионов ячеек в формате data.table, и когда mclapply отправлял результаты обратно, он столкнулся с этим ограничением.
Стратегия «разделяй и властвуй» не так сложна, и она работает. Я понимаю, что это взлом, и нужно иметь возможность положиться на mclapply.
Вместо одного большого списка создайте список списков. Каждый вложенный список меньше, чем исправленная версия, и затем вы загружаете их в mclapply разбиением на части. Вызовите это file_map
. Результатом является список списков, поэтому вы могли бы затем использовать специальную функцию double concatenate do.call
. В результате каждый раз, когда mclapply завершает работу, размер сериализованного необработанного вектора становится управляемым.
Просто перебирайте меньшие фрагменты:
collector = vector("list", length(file_map)) # more complex than normal for speed
for(index in 1:length(file_map)) {
reduced_set <- mclapply(file_map[[index]], function(x) {
on.exit(message(sprintf("Completed: %s", x)))
message(sprintf("Started: '%s'", x))
readBamGappedAlignments(x)
}, mc.cores=10)
collector[[index]]= reduced_set
}
output = do.call("c",do.call('c', collector)) # double concatenate of the list of lists
В качестве альтернативы, сохраните выходные данные в базе данных по ходу работы, например, в SQLite.