迭代任意内存和可能的对齐问题
Iterating arbitrary memory and possible alignment issues
我正在用 C 语言实现一个简单的哈希映射,因此我实现了一个通用且简单的哈希函数,它具有以下实现:
static inline int64_t hash(void_t *key, size_t ksize)
{
int64_t hash = 0;
char_t *key_str = key;
for (size_t i = 0; i < ksize; i++)
{
char_t c = key_str[i];
hash = 31 * hash + c;
}
return hash;
}
我想知道这样实现是否更好:
static inline int64_t hash_x64(void_t *key, size_t ksize)
{
int64_t hash = 0;
size_t remain_ksize = ksize;
size_t i = 0;
while (remain_ksize >= sizeof(int64_t))
{
int64_t *val = key + i;
hash = 31 * hash + *val;
remain_ksize -= sizeof(int64_t);
i += sizeof(int64_t);
}
char_t *key_str = key;
for (; i < remain_ksize; i++)
{
char_t c = key_str[i];
hash = 31 * hash + c;
}
return hash;
}
这是否违反任何对齐/别名规则?此代码在 x64 架构上是否被认为是安全的?它会在 x64 上执行得更快,还是编译器已经针对底层架构优化了哈希函数?
不能保证传入的缓冲区在 64 位边界上正确对齐。因此,后一种代码存在由于未对齐的内存评估而崩溃的风险。根据传入的内容,可能还存在严格的别名问题。
最好一次读取一个字节。它避免了这两个问题,并且性能上的任何差异都可能是微不足道的。
我正在用 C 语言实现一个简单的哈希映射,因此我实现了一个通用且简单的哈希函数,它具有以下实现:
static inline int64_t hash(void_t *key, size_t ksize)
{
int64_t hash = 0;
char_t *key_str = key;
for (size_t i = 0; i < ksize; i++)
{
char_t c = key_str[i];
hash = 31 * hash + c;
}
return hash;
}
我想知道这样实现是否更好:
static inline int64_t hash_x64(void_t *key, size_t ksize)
{
int64_t hash = 0;
size_t remain_ksize = ksize;
size_t i = 0;
while (remain_ksize >= sizeof(int64_t))
{
int64_t *val = key + i;
hash = 31 * hash + *val;
remain_ksize -= sizeof(int64_t);
i += sizeof(int64_t);
}
char_t *key_str = key;
for (; i < remain_ksize; i++)
{
char_t c = key_str[i];
hash = 31 * hash + c;
}
return hash;
}
这是否违反任何对齐/别名规则?此代码在 x64 架构上是否被认为是安全的?它会在 x64 上执行得更快,还是编译器已经针对底层架构优化了哈希函数?
不能保证传入的缓冲区在 64 位边界上正确对齐。因此,后一种代码存在由于未对齐的内存评估而崩溃的风险。根据传入的内容,可能还存在严格的别名问题。
最好一次读取一个字节。它避免了这两个问题,并且性能上的任何差异都可能是微不足道的。