转换size_t以允许std :: vector中的更多元素

时间:2012-06-22 07:12:37

标签: c++

我需要在std::vector中存储大量元素(超过unsigned int允许的2 ^ 32-1)。据我所知,这个数量受std::size_t unsigned int类型的限制。我可以通过转换为std::size_t来更改此unsigned long吗?它会解决这个问题吗?

如果那是不可能的,假设我用64位编译。这会在没有任何修改的情况下解决问题吗?

3 个答案:

答案 0 :(得分:6)

size_t是一种可以保存任何可分配内存块大小的类型。因此,您无法分配比size_t更适合的内存,因此无法以任何方式存储更多元素。

以64位编译将允许它,但意识到阵列仍然需要适合内存。 2 32 是40亿,所以你要超过4 * sizeof(元素)GiB的内存。超过8 GiB的RAM仍然很少,因此看起来不合理。

我建议用STXXL中的一个替换矢量。它使用外部存储,因此您的向量不受RAM的限制。该图书馆声称可以轻松处理数TB的数据。

(编辑)迂腐:size_t需要保持最大单个对象的大小,而不一定是所有可用内存的大小。在分段存储器模型中,当每个对象必须存在于单个段中时,它仅需要适应偏移,但是对于不同的段,可以访问更多的存储器。甚至可以在x86上使用它与PAE,“长”内存模型。但是我没有看到任何人真正使用它。

答案 1 :(得分:3)

有很多事情要说。

首先,分别关于32位系统和64位系统上 std::size_t 的大小。这就是标准所说的关于std::size_t(§18.2/ 6,7)的内容:

  

6类型size_t是一种实现定义的无符号整数类型,其大小足以包含大小   以字节为单位的任何对象。

     

7 [注意:建议实现选择ptrdiff_tsize_t整数的类型   转换等级(4.13)不大于signed long int的转换等级,除非需要更大的尺寸   包含所有可能的值。 - 结束说明]

由此可见,std::size_t在32位系统上至少 32位,并且64位至少 64位比特系统。它可能更大,但显然没有任何意义。

第二,关于类型转换的想法:为了实现这一点,即使在理论上,你也必须施展(或者更确切地说) :重新定义std::vector本身实现中的类型,无论它出现在何处。

第三次,当你说你需要“32位”的超大矢量时,这是否意味着你想在32位系统上使用它?在这种情况下,正如其他人已经指出的那样,你想要的是不可能的,因为32位系统根本没有那么多内存。

但是,第四,如果您想要的是在64位计算机上运行程序,并且只使用32位数据类型来引用数字的元素,但可能是一个64位类型来指代以字节为单位的总大小,那么std::size_t是不相关的,因为它用于指代元素的总数和各个元素的索引,但是不是以字节为单位的大小。

最后,如果您使用的是64位系统,并希望使用类似std::vector的极端比例,那肯定是可能的。具有32 GB,64 GB甚至1 TB主内存的系统可能不是很常见,但绝对可用。

然而,要实现这样的数据类型,只需在一个连续的块中分配千兆字节的内存 (这是std::vector的作用),原因如下:

  • 除非在初始化时一次性确定向量的总大小,否则向量将被调整大小,很可能重新分配,可能多次添加元素。重新分配极大的向量可能是一个耗时的操作。 [我已将此项目添加为编辑至我的原始答案。的
  • 操作系统将难以提供如此大部分的未分段内存,因为并行运行的其他进程也需要内存。 [编辑:正如评论中正确指出的那样,这在今天使用的任何标准操作系统上都不是真正的问题。]
  • 在非常大的服务器上,你也有数十个CPU和典型的NUMA类型的内存架构,显然最好使用相对较小的内存块,并且有多个线程(可能每个运行在不同的内核上)访问各种并行的矢量块。

<强>结论

A)如果您使用的是32位系统,并且想要使用大的矢量,那么使用基于磁盘的方法(如@JanHudec建议的那种方法)是唯一的东西这是可行的

B)如果您可以访问具有数十或数百GB的大型64位系统,则应该查看将整个内存区域划分为块的实现。基本上类似于std::vector<std::vector<T>>的东西,其中每个嵌套向量代表一个块。如果所有块都已满,则附加一个新块等。为此也可以直接实现迭代器类型。当然,如果你想进一步优化它以利用多线程和NUMA功能,它将变得越来越复杂,但这是不可避免的。

答案 2 :(得分:0)

vector可能是您错误的数据结构。它需要存储在单个内存块中,这受到size_t大小的限制。这可以通过编译64位系统来增加,但是你不能在可能需要的32位系统上运行。

如果您不需要vector的特定特征(特别是O(1)查找和连续的内存布局),则std::list等其他结构可能适合您,没有大小限制除了计算机可以物理处理的内容,因为它是链接列表而不是方便包装的数组。