C ++ 2.5字节(20位)整数

时间:2010-09-16 09:25:32

标签: c++ integer operator-overloading cuda byte

我知道这很荒谬,但我需要它来进行存储优化。有没有什么好的方法在C ++中实现它?

它必须足够灵活,以便我可以将其用作普通数据类型,例如Vector< int20 >,运算符重载等。

10 个答案:

答案 0 :(得分:9)

如果存储是您主要关注的问题,我怀疑您需要相当多的20位变量。把它们成对存放怎么样?你可以创建一个代表两个这样的变量的类,并将它们存储在2.5 + 2.5 = 5个字节中。

要方便地访问变量,您可以覆盖[] - 操作符,以便编写:

int fst = pair[0];
int snd = pair[1];

因为您可能希望允许进行操作,例如

pair[1] += 5;

您不希望返回支持字节的副本,而是 引用 。但是,你不能返回对后备字节的直接引用(因为它会弄乱它的相邻值),所以你实际上需要为后备字节返回代理(反过来)有一个对后备字节的引用)并让代理重载相关的运算符。

事实上,正如@Tony建议的那样,你可以将其概括为一个容纳N个这样的20位变量的通用容器。

(我自己在向量的专门化中做了这个,以便有效地存储布尔值(作为单个位)。)

答案 1 :(得分:6)

不......你不能把它当作单一的价值语义类型......任何类数据都必须是8位字符大小的倍数(邀请所有关于CHAR_BITS等的常见讽刺)。

那就是说,让我们抓住稻草......

不幸的是,你显然处理了很多数据项。如果这超过64k,任何代理对象进入打包值的自定义容器也可能需要一个&gt; 16位索引/句柄,但仍然是我能看到的少数几个值得进一步考虑的可能性之一。如果您只是在一个时间点为一小部分值积极处理并需要值语义行为,那么它可能是合适的。

struct Proxy
{
    Int20_Container& container_;  // might not need if a singleton
    Int20_Container::size_type index_;
    ...
};

因此,代理可能是32位,64位或更多位 - 只有当您可以从索引到容器中动态创建它们,让它们直接写回容器并使它们保持短暂时,潜在的好处同时很少。 (一种简单的方法 - 不一定是最快的 - 实现这个模型是使用STL位集或向量作为Int20_Container,并且在index_中存储20倍的逻辑索引,或者在运行中相乘。)

虽然你的值超过20位空间,但实际使用中你不到64k个不同的值,这也是模糊的可能。如果您对数据集有一些了解,可以创建一个查找表,其中16位数组索引映射到20位值。

答案 2 :(得分:4)

使用课程。只要你尊重copy / assign / clone / etc ... STL语义,你就不会有任何问题。

但它不会优化计算机上的内存空间。特别是如果你放入一个平面阵列,20bit可能会在32位边界上对齐,所以20bit类型的好处是没用的。

在这种情况下,您需要定义自己的优化阵列类型,它可以与STL兼容。但是不要指望它快。它不会。

答案 3 :(得分:3)

使用位域。 (我真的很惊讶没有人建议过。)

struct int20_and_something_else {
    int less_than_a_million : 20;
    int less_than_four_thousand : 12; // total 32 bits
};

这仅适用于结构中元素的相互优化,您可以使用其他一些数据来弥补差距。但它的效果非常好!

如果你真的需要优化一个20位数字的巨大数组,那么就有:

struct int20_x3 {
    int one : 20;
    int two : 20;
    int three : 20; // 60 bits is almost 64

    void set( int index, int value );
    int get( int index );
};

如果您愿意,可以添加getter / setter函数以使其更漂亮,但是您不能获取位域的地址,并且它们不能参与数组。 (当然,您可以拥有struct的数组。)

用作:

int20_x3 *big_array = new int20_x3[ array_size / 3 + 1 ];

big_array[ index / 3 ].set( index % 3, value );

答案 4 :(得分:2)

您可以使用C ++ std::bitset。将所有内容存储在bitset中并使用正确的索引(x20)访问您的数据。

答案 5 :(得分:1)

您可以使用union关键字创建位字段。当比特字段是必需的时候我已经习惯了。否则,您可以创建一个包含3个字节的类,但通过按位操作只会暴露最重要的20个字节。

答案 6 :(得分:1)

你将无法将20位作为一种类型(即使使用位打包结构),因为它总是与一个字节对齐(在最小的粒度处)。 Imo唯一的方法,如果你必须有20位,就是创建一个比特流来处理数据(你可以重载以接受索引等)

答案 7 :(得分:0)

据我所知,这是不可能的。

最简单的选择是定义一个自定义类型,它使用int32_t作为后备存储,并将适当的数学实现为覆盖操作符。

为了获得更好的存储密度,您可以将3个int20存储在一个int64_t值中。

答案 8 :(得分:0)

只是一个想法:使用优化存储(两个实例为5个字节),对于操作,将其转换为32位int然后再返回。

答案 9 :(得分:0)

虽然可以通过多种方式实现这一目标。 一种可能性是使用bit twidling将它们存储为5字节数组的左右部分,其中存储/检索类将yoiur所需的数组条目转换为byte5 []数组中的数组条目并提取左边的权限一半是适当的。

然而,在大多数硬件上,要求整数是字对齐的,以及提取整数的位,你需要一些比特来正确对齐它。

我认为增加交换空间并让虚拟内存处理你的大型阵列会更有效(在所有20 vs 32之后节省不多!)总是假设你有64位操作系统。