2015-12-08 7 views
6

У меня очень большая матрица, которую я пытаюсь запустить через glmnet на сервере с большим количеством памяти. Он отлично работает даже на очень больших объемов данных до определенной точки, после чего я получаю следующее сообщение об ошибке:Ограничение размера вектора R: «длинные векторы (аргумент 5) не поддерживаются в .C«

Error in elnet(x, ...) : long vectors (argument 5) are not supported in .C 

Если я правильно понял, это вызвано ограничением в R, которые не могут иметь любой вектор с длиной больше чем INT_MAX. Это верно? Есть ли доступные решения для этого, которые не требуют полной перезаписи glmnet? Использует ли какой-либо из альтернативных переводчиков R (Riposte и т. Д.) Это ограничение?

Спасибо!

+0

Во время вашего кода вы выполняете подмножество матрицы? Возможно, я ошибаюсь, но вы не можете выполнить подмножество матрицы, если в матрице содержится более 36 миллиардов элементов. В этом случае вы должны подмножить матрицу так, как если бы это был огромный атомный вектор (что на самом деле это потому, что матрица - это всего лишь vecotr с атрибутом dimesion). – SabDeM

+0

В моем коде я использую файл с поддержкой bigmatrix, чтобы избежать этих проблем, но когда я запускаю glmnet, я должен передать его как R-матрицу следующим образом: 'theMatrix [,]'. – Danny

+2

Привет, Дэнни. Мой комментарий напрямую не связан с вопросом, но mb это поможет. Взгляните на пакет pirls от Michael Kane - https://github.com/kaneplusplus/pirls. Мб этот решатель работает с длинными векторами. –

ответ

4

Поскольку версия 3 R поддерживает длинные векторы. Длинный вектор индексируется double. Длинный вектор может быть базой для матрицы или более чем 2-мерной матрицы, если каждый размер достаточно мал, чтобы быть проиндексированным integer. Длинные векторы не могут быть переданы в собственный код через .C и .Fortran. Сообщение об ошибке, которое вы получаете, связано с тем, что длинный вектор передается через .C.

Длинные векторы могут быть переданы через .Call. Таким образом, до тех пор, пока собственный код glmnet может поддерживать длинные векторы (64-разрядные индексы) или может быть изменен/скомпилирован для его поддержки, нужно будет только изменить интерфейс между R и собственным кодом glmnet. Вы можете сделать это вручную на C, и для этой задачи также есть новый пакет с именем dotCall64. Часть изменения интерфейса решает, когда копировать аргументы - .C/.Fortran превентивно копирует, но вы не хотите делать это без необходимости с большими структурами данных.

Я думаю, что трудность изменения собственного кода glmnet для поддержки 64-битных индексов зависит от фактического кода (который я только смотрел, но не работал). Легко переключить все целые числа (или явно или неявно 32-битные целые числа) в коде Fortran на 64-разрядные. Проблемы возникают, когда некоторые целые числа должны оставаться 32 бит, и это произойдет, например. для целых векторов, переданных из/в R-код, поскольку R использует 32-битные целые числа (даже в длинных векторах). В glmnet есть такие целые векторы. Насколько сложна модификация, тогда зависит от того, насколько чистым является исходный код Fortran (например, если он использует отдельные целочисленные переменные для индексирования и доступа к значениям целых массивов и т. Д.).

Экспериментальные реализации подмножеств R, как и Riposte, не помогут.

+0

Спасибо за информацию, но некоторые копания, похоже, указывают на то, что для переключения с .C на .Call требуются значительные изменения в базовом коде Fortran. Именно этого я и стараюсь избегать. Похоже, что это просто не может быть решением, которое соответствует моим потребностям. – Danny

+1

Я обновил свой ответ. Я думаю, что сложность зависит от реального кода, поэтому люди, которые работали с этим кодом, могли бы дать лучший ответ. Мое предположение: через день или два из программирования вы либо сделали бы это, либо получили бы хорошую оценку. Конечно, это не должно быть полной перезаписи. –

+0

Это похоже на это! Ключом для меня был пакет dotCall64. Использование .Call напрямую было немного меньше времени и сложности, на которые у меня есть время, но с dotCall64 мне просто пришлось реплицировать вызовы .Fortran и добавить список типов данных для входных переменных. Идентификация правильных типов данных заняла немного времени, но не была слишком сложной. Есть проблемы с памятью, но я думаю, что смогу их обойти. Большое спасибо Томасу! – Danny

2

Существует заметка в ?"long vector", которая гласит:

However, compiled code typically needs quite extensive changes. Note that the .C and .Fortran interfaces do not accept long vectors, so .Call (or similar) has to be used.

elnet делает .Fortran звонки. Вам нужно будет изменить функцию на использование .Call, возможно, через оболочку C, которая вызывает код FORTRAN, и, возможно, переписать и скомпилировать соответствующий код FORTRAN для обработки длинных векторов.

+0

Спасибо за информацию, но некоторые копания, похоже, указывают на то, что для переключения с .C на .Call требуются серьезные изменения в базовом коде Fortran. Именно этого я и стараюсь избегать. Похоже, что это просто не может быть решением, которое соответствует моим потребностям. – Danny

+0

Нет, если базовый код привязан к 32-битным векторам, я боюсь, что вы застряли с ним. – James