mclapply с большими объектами — «сериализация слишком велика для хранения в необработанном векторе»

#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.