【问题标题】:R vector size limit: "long vectors (argument 5) are not supported in .C"R 向量大小限制:“.C 中不支持长向量(参数 5)”
【发布时间】:2016-03-13 22:47:23
【问题描述】:

我有一个非常大的矩阵,我试图在具有大量内存的服务器上运行 glmnet。即使在非常大的数据集上达到某个点,它也能正常工作,之后我收到以下错误:

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

如果我理解正确,这是由 R 中的限制引起的,它不能有任何长度超过 INT_MAX 的向量。那是对的吗?是否有任何不需要完全重写 glmnet 的可用解决方案?是否有任何替代的 R 解释器(Riposte 等)解决了这个限制?

谢谢!

【问题讨论】:

  • 在您的代码中,您是否执行了矩阵的子集?我可能错了,但如果矩阵有超过 360 亿个元素,你就不能执行矩阵子集。在这种情况下,您必须对矩阵进行子集化,就好像它是一个巨大的原子向量(实际上是因为矩阵只是一个具有维度属性的向量)。
  • 在我的代码中,我使用文件支持的 bigmatrix 来避免这些问题,但是当我运行 glmnet 时,我必须将它作为 R 矩阵传递,如下所示:theMatrix[,]
  • 嗨,丹尼。我的评论与问题没有直接关系,但它会有所帮助。看看 Michael Kane 的 pirls 包 - github.com/kaneplusplus/pirls。 Mb 这个求解器适用于长向量。
  • 问题确实是 glmnet 中的底层设计,以及它对(有效地弃用和不鼓励的.C())接口的使用。 Mike Kane 仔细研究了一下,这是 pirls 确实应该提供一些东西。它当然更小/更年轻/不太好测试,所以 YMMV。
  • 刚刚发现另一个非常有前途的包 - github.com/jaredhuling/oem

标签: r vector bigdata scalability glmnet


【解决方案1】:

由于版本 3 R 支持长向量。长向量由double 索引。长向量可以是矩阵或多于 2 维数组的基础,只要每个维度都小到可以被 integer 索引。长向量不能通过.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,将无济于事。

【讨论】:

  • 感谢您的信息,但一些挖掘似乎表明从 .C 切换到 .Call 需要对底层 Fortran 代码进行重大更改。这正是我想要避免的。听起来可能根本没有适合我需求的解决方案。
  • 我已经更新了我的回复。我认为难度取决于实际代码,因此使用该代码的人可以给出最佳答案。我的猜测:经过一两天的编程,你要么完成它,要么有一个很好的估计。当然,这不应该是完全重写。
  • 好像已经做到了!对我来说关键是 dotCall64 包。直接使用 .Call 有点超出我现在有时间的时间和复杂性,但使用 dotCall64 我只需复制 .Fortran 调用并为输入变量添加数据类型列表。识别正确的数据类型需要一些时间,但并不难。内存仍然存在一些问题,但我想我可以解决它们。非常感谢托马斯!
【解决方案2】:

?"long vector" 中有一条说明:

但是,编译后的代码通常需要进行大量更改。笔记 .C 和 .Fortran 接口不接受长向量,所以 .Call(或类似的)必须使用。

elnet 拨打.Fortran 电话。您必须修改函数以使用 .Call,可能通过调用 FORTRAN 代码的 C 包装器,并可能重写和编译相关的 FORTRAN 代码以处理长向量。

【讨论】:

  • 感谢您的信息,但一些挖掘似乎表明从 .C 切换到 .Call 需要对底层 Fortran 代码进行重大更改。这正是我想要避免的。听起来可能根本没有适合我需求的解决方案。
  • 不,如果底层代码与 32 位向量结合,恐怕你会卡住。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 2016-06-21
  • 2014-08-08
  • 2014-06-07
  • 1970-01-01
  • 2014-07-18
相关资源
最近更新 更多