struct Val4 {
char hi[4];
unsigned int low[4];
}
long getLong( const Val4 &pack, int ix ) {
int hi= pack.hi[ix]; // preserve sign into 32 bit
return long( (((unsigned long)hi) << 32) + (unsigned long)pack.low[i]);
}
void setLong( Val4 &pack, int ix, long val ) {
pack.low[ix]= (unsigned)val;
pack.hi[ix]= (char)(val>>32);
}
这些也可以这样使用:
Val4[SIZE] vals;
long getLong( int ix ) {
return getLong( vals[ix>>2], ix&0x3 )
}
void setLong( int ix, long val ) {
setLong( vals[ix>>2], ix&0x3, val )
}
有一种情况是次优的,那就是当您真正随机访问许多项时,因此每次对 int 数组的访问都会导致缓存丢失——这里每次都会有两次缓存丢失。为了避免这种情况,定义一个32字节结构,其中包含一个包含6个 uint32 _ t 的数组、一个包含6个 uint8 _ t 的数组和两个未使用的字节(每个数字412/3 rd) ; 访问一个项的代码稍微复杂一些,但是该项的两个组件都在同一个缓存行中。
这就需要内存中的流式无损数据压缩。如果这是针对大数据应用程序的,密集打包技巧充其量只是需要相当不错的中间件或系统级支持的战术解决方案。他们需要彻底的测试,以确保能够恢复所有的位完好无损。而且由于对 CPU 缓存架构的干扰(例如缓存线路与封装结构) ,性能影响非常重要,并且非常依赖于硬件。有人提到了复杂的网状结构: 这些结构通常经过了微调,以便与特定的缓存架构协同工作。
从需求中并不清楚 OP 是否需要随机访问。考虑到数据的大小,很可能只需要对相对较小的数据块进行本地随机访问,并按层次进行检索。即使是硬件在大内存大小(NUMA)时也会这样做。正如无损电影格式所显示的那样,应该可以在不必将整个数据集加载到热内存(从压缩的内存备份存储)的情况下获得块(“帧”)的随机访问。
我知道有一个快速数据库系统(KX Systems 的 kdb 就是其中之一,但我知道还有其他系统)可以通过从后台存储无缝内存映射大型数据集来处理极大的数据集。它可以选择透明地压缩和扩展动态数据。
40-bit word to access: 32-bit accesses 64bit-accesses
word 0: [0,40) 2 1
word 1: [40,80) 2 2
word 2: [80,120) 2 2
word 3: [120,160) 2 2
word 4: [160,200) 2 2
word 5: [200,240) 2 2
word 6: [240,280) 2 2
word 7: [280,320) 2 1
不要使用位字段,除非你已经准备好支付它们的成本。例如,如果您有一个位字段数组,并希望将其划分为多个线程进行处理,那么您将陷入困境。根据 C + + 11的规则,位字段都形成一个内存位置,因此一次只能由一个线程访问 (这是因为打包位字段的方法是实现定义的,所以 C + + 11不能帮助您以非实现定义的方式分发它们)