在这个项目中我需要创建一个巨大的数组(希望我能创造一个大如〜7.13e + 17,但这一目标仍然高达遥遥领先。)
那调用创建一个专用结构,一个la digital tree(或b-tree),键是索引,以避免执行大量分配。
大量分配和特别是重新分配可能会导致不必要的memory fragmentation。如果将大数组分成更小的块,那么不仅数组扩展变得容易,而且稀疏数组的呈现变得可能。
N.B. ~7.13e+17
大约有60位长。你甚至有硬件可以支持那么多的RAM吗?这并不是说我密切关注着行业,但是我简要地听说过使用58位地址总线的NUMA拱形结构 - 但没有任何关于60位拱形结构的东西。
数组内的每个单元格可以包含三个值之一:0,1,2.2。
如果单元格可能只包含3个值(2.2可以表示为2),使其成为2位信息。这意味着您可以将数值打包成uint32_t
32值。
您可以尝试找到一些现有的数字树实现(或自己推出)并将其用作索引的关键高位。原始索引的剩余位是树叶的索引,它将是一个具有打包值的数组。为了举例说明代替特里结构的使用std::map
,未测试:
enum {
LS_BITS = 16,
MS_BITS = 64-LS_BITS
};
enum {
VALUE_BITS = 2,
VALUE_MASK = ((1<<VALUE_BITS)-1)
};
// this represents an array of `1<<LS_BITS` values
struct leaf_node {
uint64_t packed_data[ ((1<<LS_BITS)*VALUE_BITS)/(sizeof(uint64_t)*8) ];
};
// that should be a trie, to provide faster look-up
typedef std::map< uint64_t, leaf_node > big_array_type;
void
big_array_set_value(big_array_type &b, uint64_t index, uint64_t value)
{
leaf_node &n = b[index >> LS_BITS];
uint64_t li = index & ((1<<LS_BITS)-1);
li *= VALUE_BITS; // convert into bit offset
uint64_t &x = n.packed_data[ li/(sizeof(uint64_t)*8) ];
li %= (sizeof(uint64_t)*8);
x = (x & (VALUE_MASK<<li)) | (value << li);
}
int
big_array_get_value(big_array_type &b, uint64_t index, uint64_t value)
{
leaf_node &n = b[index >> LS_BITS];
uint64_t li = index & ((1<<LS_BITS)-1);
li *= VALUE_BITS; // convert into bit offset
uint64_t &x = n.packed_data[ li/(sizeof(uint64_t)*8) ];
li %= (sizeof(uint64_t)*8);
return (x >> li) & VALUE_MASK;
}
这样一个静止废物的信息比特0.5自存储为2个比特什么允许4个值,但只有3被使用。这也可以得到改善,但是访问性能成本要高得多。
你是否拥有一家记忆工厂? – Duck 2010-09-12 17:30:05
您可以用两位表示0,1,2,因此每个字节可以存储4个值。做一个快速的划分,每个字节7.13e17个项目/ 4个项目给出〜162,117 TB的数据。这是非常不切实际的,我认为你的第一步*是设计一种完全不同的方法。 – 2010-09-12 17:36:11
我编辑了我的主帖,以良好的方式回答您的评论。 – Urielnam 2010-09-12 17:48:39