表示Connect Four的转置表(通常是哈希表) 游戏,我想有效地使用内存(以尽可能多的存储 元素数量)。一个表元素必须存储以下信息:
首先我尝试了以下数据结构,需要24个字节:
struct TableEntry1
{
unsigned __int64 lock;
unsigned char move;
short score;
enum { VALID, UBOUND, LBOUND } flag;
char height;
};
重新排列元素后需要16个字节(我找到了answer 行为):
struct TableEntry2
{
unsigned __int64 lock;
enum { VALID, UBOUND, LBOUND } flag;
short score;
char height;
unsigned char move;
};
我的最后一次尝试是:
struct TableEntry3
{
unsigned __int64 lock;
unsigned int move:3;
int score:12;
enum { VALID, UBOUND, LBOUND } flag:2;
int height:7;
};
还需要16个字节。是否有可能改变结构 仅使用12个字节(在32位架构上)?为什么编译器不能让我最后一次尝试12个字节?
谢谢!
编辑属性lock
是检测哈希冲突的唯一元素ID。
答案 0 :(得分:6)
是的,因为您只有88位信息,所以可以将其打包成96位(12字节);但是,你真的需要吗?在极端情况下,请记住这样的打包会降低运行时性能。
如果您将这些文件存储到磁盘中,考虑到之前的微小效率会更有意义,但这是这种情况吗?你有没有看过内存使用方面的问题?您需要多少内存,目前有16个字节的对象,以及它与您的计划限制有多接近?尝试在不回答最后两个问题的情况下优化运行时内存使用是premature。
除此之外,我怀疑你的编译器在结构的末尾填充,所以__int64总是在8字节边界上对齐。考虑一个长度为2的数组:大小为12字节,最多一个__int64子对象可以是8字节对齐。
答案 1 :(得分:3)
使用非标准构造(如Visual Studio #pragma
pack:
#pragma pack(1)
struct TableEntry3
{
unsigned __int64 lock;
unsigned int move:3;
int score:12;
enum { VALID, UBOUND, LBOUND } flag:2;
int height:7;
};
在这里,sizeof(TableEntry3)
为我产生了12个。
答案 2 :(得分:2)
根据你如何实现锁定,可以减小锁定字段的大小(我假设这是一个典型的SMP锁定SMP机器)
一种选择是减少锁的数量。也就是说,有一个单独的,较小的数组锁,并在此处锁定从数组元素派生的元素。也就是说,如果您要访问转置表元素t
,请使用锁t % locktablesize
。锁定表不必与转置表一样大。
使用这种方法和你的TableEntry2
字段顺序,假设你的锁表大小是转置表的一半(可能比必要的大),你可以在不损失性能的情况下减少12个字节由于比特移位操作 - 这种性能损失可能非常显着,因此能够避免这种情况总是有帮助的。