2015-12-08 232 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

在您的代码中,您是否执行矩阵的子集化?我可能是错的,但如果矩阵有超过360亿个元素,则不能执行矩阵子集。在这种情况下,你必须将矩阵子集看作是一个巨大的原子向量(事实上它是因为矩阵只是一个具有dimesion属性的vecotr)。 – SabDeM

+0

在整个我的代码中,我使用一个支持bigmatrix的文件来避免这些问题,但是当我运行glmnet时,我必须将它作为R矩阵传递,如下所示:'theMatrix [,]'。 – Danny

+2

嗨Danny。我的评论与问题没有直接关系,但是它会有所帮助。看看Michael Kane的pirls包 - https://github.com/kaneplusplus/pirls。 Mb这个求解器适用于长载体。 –

回答

4

由于版本3 R支持长向量。长向量由double索引。只要每个维度足够小以便可由integer索引,则长矩阵可以是矩阵或多于2维阵列的基础。长向量不能通过.C.Fortran传递给本地代码。您收到的错误消息是因为一个长矢量正通过.C传递。

长向量可以通过.Call传递。所以,只要glmnet的本地代码可以支持长向量(64位索引)或者可以修改/编译以支持它,就只需修改R和glmnet的本地代码之间的接口即可。您可以在C中手动执行此操作,并且此任务还有一个名为dotCall64的新程序包。修改接口的一部分是决定何时复制参数 - .C/.Fortran预防性复制,但您不希望在大型数据结构中进行不必要的操作。

我认为改变glmnet的本地代码以支持64位索引的难度取决于实际的代码(我只看过但从未使用过)。将Fortran代码中的所有整数(或显式或隐式32位整数)切换为64位很容易。当一些整数必须保持32位时会出现问题,这会发生,例如,对于从/到R代码传递的整数向量,因为R使用32位整数(即使在长向量中也是如此)。在glmnet中有这样的整数向量。修改的难度取决于原始Fortran代码的干净程度(例如,如果它使用单独的整数变量来索引和访问整型数组的值等)。

R的子集的实验性实现,如Riposte,将无济于事。

+0

感谢您的信息,但是一些挖掘似乎表明,从.C切换到.Call需要对基础Fortran代码进行重大更改。这正是我想要避免的。听起来好像根本没有适合我需求的解决方案。 – Danny

+1

我已经更新了我的回复。我认为难度取决于实际代码,因此使用该代码的人可以给出最佳答案。我的猜测是:在编程一两天之后,你要么完成它,要么有一个好的估计。当然,这不应该是一个完整的重写。 –

+0

这似乎已经做到了!对我来说关键是dotCall64软件包。直接使用.Call有点超出了我现在有时间和复杂性,但是使用dotCall64,我只需重新命名.Fortran调用并为输入变量添加一个数据类型列表。识别正确的数据类型需要一些时间,但不是太困难。记忆仍然存在一些问题,但我想我可以解决它们。非常感谢Tomas! – 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,可能通过调用FORTRAN代码的C封装器,并可能重写和编译相关的FORTRAN代码来处理长向量。

+0

感谢您的信息,但是一些挖掘似乎表明,从.C切换到.Call需要对基础Fortran代码进行重大更改。这正是我想要避免的。听起来好像根本没有适合我需求的解决方案。 – Danny

+0

不,如果底层代码被嵌入到32位向量中,恐怕你会被卡住。 – James