为什么R中的逻辑(布尔值)需要4个字节?

时间:2012-02-07 14:44:36

标签: r memory boolean

对于逻辑值的向量,当一个位向量每个条目消耗1位时,为什么R会分配4个字节? (有关示例,请参阅this question。)

现在,我意识到R还有助于NA值的存储,但不能用额外的位向量来完成?换句话说,为什么只使用廉价的两位数据结构就足够了呢?

对于它的价值,Matlab使用1个字节作为逻辑,但它并不能促进NA值。我不确定为什么MathWorks不满足于一位功能,更不用说两位数据结构了,但他们有花哨的裤子营销人员...... [我要喝牛奶"两个位"尽管这个问题值得。 ; - )]


更新1.我认为所提供的架构原因有一定道理,但事后有点感觉。 我没有检查32位或16位R以查看它们的逻辑有多大 - 这可以为这个想法提供一些支持。the R Internals manual看来,逻辑向量( LGLSXP)和整数(INTSXP)在每个平台上都是32位。我可以理解整数的通用大小,与字大小无关。类似地,逻辑的存储似乎也与字大小无关。但它太大了。 :)

另外,如果单词大小参数如此强大,我觉得看到Matlab(我认为它是32位Matlab)只消耗1个字节似乎很奇怪 - 我想知道MathWorks是否选择了更高的内存效率需要权衡编程复杂性以及查找子词对象的其他开销。

此外,肯定还有其他选择:正如Brian Diggs所说,bit包有助于位向量,这对于上述问题中的问题非常有用(任务的8X-10X加速是通过从4字节logical值转换为位向量获得的。虽然访问内存的速度很重要,但是从信息论角度来看,移动30-31个额外的无信息位是浪费的。例如,可以使用类似于整数described here的内存技巧 - 获取一堆额外的内存(V单元),然后在位级处理事务(la bit())。为什么不这样做并为长矢量保存30位(值为1,NA为1)?

如果我的RAM和计算速度受到布尔值的影响,我打算切换到使用bit,但这是因为在某些情况下节省97%的空间很重要。 :)

我认为这个问题的答案来自对R设计或内部有更深入理解的人。最好的例子是Matlab在逻辑上使用不同的大小,在这种情况下,内存字大小不是答案。 Python可能与R类似,因为它的价值。

短语的一个相关方法可能是:为什么LGLSXP在所有平台上都是4个字节? (CHARSXP通常是否较小,并且不会起作用?为什么不进行更小规模,只是过度分配?)(更新使用{{1>的想法可能是假的,因为CHARSXP上的操作并不像整数那样有用,例如CHARSXP。使用与字符相同的数据结构可能会节省空间,但会限制哪些现有的方法可以对它进行操作。更合适的考虑因素是使用较小的整数,如下所述。)


更新2.这里有一些非常好的和有启发性的答案,特别是关于一个应该如何为了速度和编程效率的目标实现布尔值的检索和处理。我认为Tommy的答案特别合理,因为为什么在R中出现这种情况,这似乎来自于两个前提:

  1. 为了支持对逻辑向量的添加(注意"逻辑"由编程语言/环境定义,并且与布尔值不同),最好通过重用来实现用于添加整数的代码。在R的情况下,整数消耗4个字节。在Matlab的情况下,最小的整数是1个字节(即sum)。这可以解释为什么不同的东西会为逻辑写作带来麻烦。 [对于不熟悉R的人,它支持对逻辑进行许多数值运算,例如int8sum(myVector)等。]

  2. 传统支持使得除了R和S-Plus已经做了很长时间以外的其他事情非常困难。而且,我怀疑在S,S-Plus和R的早期,如果有人做了很多布尔操作,他们用C做了它们,而不是试图在R中用逻辑做很多工作。

  3. 对于如何实现更好的布尔处理的目的,其他答案非常棒 - 不要天真地假设一个人可以获得任何单独的位:它最有效地加载一个单词,然后掩码Dervall描述的那些不感兴趣的位。如果为R的布尔操作编写专门的代码(例如我在交叉表中的问题),这是非常非常有用的建议:不要迭代位,而是在单词级别工作。

    感谢所有人提供了一套非常全面的答案和见解。

3 个答案:

答案 0 :(得分:16)

根本不知道R,我怀疑与C的原因大致相同,因为加载大小等于处理器本机字大小的速度更快。

加载单个位会很慢,尤其是来自位域,因为您必须屏蔽掉不适用于您的特定查询的位。总而言之,您只需将其加载到注册表中即可完成。由于大小差异通常不是问题,因此默认实现是使用字大小的变量。如果用户想要其他东西,总是可以选择手动进行位移。

关于打包,至少在某些处理器上,它会导致从非对齐地址读取错误。因此,虽然您可以声明其中包含一个byte的结构被int包围,byte可能会被填充为大小为4个字节,无论如何。同样,我对R没有任何了解,但我怀疑出于性能原因,行为可能是相同的。

对数组中的单个字节进行寻址是非常复杂的,比如你有一个数组bitfield并想在其中寻址位x,代码就是这样:

bit b = (bitfield[x/8] >> (x % 8)) & 1

为您请求的位获取0或1。与来自布尔数组的直接数组寻址相比,获得值数x:bool a = array[x]

答案 1 :(得分:15)

了解R和S-Plus的一些内容,我会说R最有可能与S-Plus兼容,S-Plus最有可能这样做,因为它是最简单的事情。 。

基本上,逻辑向量与整数向量相同,因此sum和其他整数算法在逻辑向量上几乎没有变化。

在64位S-Plus中,整数是64位,因此也是逻辑向量!每个逻辑值 8个字节 ......

@Iterator当然是正确的,逻辑向量应该以更紧凑的形式表示。由于已经存在1 {1}字节的raw向量类型,因此对于逻辑也使用该向量类似乎是非常简单的更改。每个值2位当然会更好 - 我可能会将它们保留为两个独立的位向量(TRUE / FALSE和NA / Valid),如果没有NA,则NA位向量可能为NULL ... < / p>

无论如何,这主要是一个梦想,因为有那么多RAPI包(使用R C / FORTRAN API的包)会破坏......

答案 2 :(得分:10)

其他答案得出(可能)架构原因,逻辑向量的实现采用与整数相同的空间。我想指出实现一位(无NA)逻辑的bit包。