我需要分配一个uint64_t[1e9]
数组来计算某些东西,我知道这些项目介于(0,2 ^ 39)之间。
所以我希望数组为calloc
5 * 1e9个字节。
然后我发现,如果我想使uint64_t有意义,那么很难通过字节顺序。
应该有两种方式。
首先检查字节顺序,以便我们可以{5}将5个字节{8}整个字节中的第一个或最后一个字节。
另一种方法是使用5位移位,然后将位或它们放在一起。
我认为前者应该更快。
那么,在GCC或libc或GNU系统下,是否有任何头文件来指示当前系统是Little Endian还是Big Endian?我知道x86_64是Little Endian,但我不喜欢写一个不可移植的代码。
当然欢迎任何其他想法。
添加:
我需要使用数组来计算许多使用D-left散列的字符串。我计划使用21位的密钥和18位的计数。
答案 0 :(得分:1)
当你说“更快”时......这段代码的执行频率是多少? 5次<<8
加|
可能花费不到100ns。因此,如果该代码执行10'000次,则最多可加1(一)秒。
如果代码执行次数较少,并且您需要超过1秒才能实现endian-clean解决方案,那么您就浪费了每个人的时间。
那就是说,找出结束的解决方案很简单:
int a = 1;
char * ptr = (char*)&a;
bool littleEndian = *ptr == 1;
现在您需要一台大端机器和几个测试用例来确保您的memcpy
解决方案正常运行。请注意,您需要在两种情况之一中调用memcpy
五次以重新排序字节。
或者你可以简单地转移或者五次......
编辑我想我误解了你的问题。您是说要使用uint64_t
的最低5个字节(= 40位)作为计数器,是吗?
因此操作将被执行很多次。同样,memcpy
完全没用。我们取数0x12345678
(32位)。在内存中,看起来像这样:
0x12 0x34 0x56 0x78 big endian
0x78 0x56 0x34 0x12 little endian
如您所见,字节被交换。因此,要在两者之间进行转换,必须使用位移或字节交换。 memcpy
不起作用。
但这并不重要,因为CPU会为你做解码。您所要做的就是将位移到正确的位置。
key = item & 0x1FFFFF
count = (item >>> 21)
阅读和
item = count << 21 | key
写。现在你只需要从五个字节构建密钥就可以了:
key = (((hash[0] << 8) | (hash[1]<<8)) | ....
编辑2
看起来你有一个40位整数的数组,你想要读/写那个数组。
我有两个解决方案:只要不在不同字节序的CPU之间复制数据,使用memcpy
就可以正常工作(读取:向磁盘保存/加载数据时)。但是对于如此庞大的数组,函数调用可能太慢了。
另一个解决方案是使用两个数组:
int lower[];
unit8_t upper[]
即:将位33-40保存在 second 数组中。要读取/写入值,需要一个班次+ or
。
答案 1 :(得分:0)
如果将数字视为数字而不是字节数组,则代码将与endianess无关。因此,我会选择 shift 和或解决方案。
话虽如此,我真的没有抓住你想要做的事情?你真的需要十亿个条目,每个五个字节长吗?如果您采样的数据稀少,您可能会分配更少的内存。
答案 2 :(得分:0)
好吧,我发现内核头文件附带<asm/byteorder.h>
。
内联memcpy到while(i<x+3){++*i=++*j}
的速度可能仍然较慢,因为缓存操作比寄存器慢。
memcpy
的另一种方式是:
union dat {
uint64_t a;
char b[8];
} d;