Skip to content

Commit

Permalink
Unify the hash function of cache and map
Browse files Browse the repository at this point in the history
Based on the below performance analysis, the golden ratio hash is a
little bit better than map hash. Therefore, we unify the hash function
to golden ratio hash.

|Metric | map hash | golden ratio hash |
|----------+----------+-------------------|
|Dhrystone | 2.06 s| 2.07 s |
|Nqueens | 4.35 s| 4.25 s |
|Stream | 76.7 s| 75.59 s |
  • Loading branch information
qwe661234 committed Oct 17, 2023
1 parent f3c7b89 commit c6e7e66
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 27 deletions.
31 changes: 18 additions & 13 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@

#include "cache.h"
#include "mpool.h"

#define GOLDEN_RATIO_32 0x61C88647
#define HASH(val) \
(((val) * (GOLDEN_RATIO_32)) >> (32 - (cache_size_bits))) & (cache_size - 1)
#include "utils.h"

/* THRESHOLD is set to identify hot spots. Once the frequency of use for a block
* exceeds the THRESHOLD, the JIT compiler flow is triggered.
Expand All @@ -24,6 +21,9 @@
static uint32_t cache_size, cache_size_bits;
static struct mpool *cache_mp;

/* hash function for the cache */
HASH_FUNC_IMPL(cache_hash, cache_size_bits, cache_size);

#if RV32_HAS(ARC)
/* The Adaptive Replacement Cache (ARC) improves the traditional LRU strategy
* by dividing the cache into two lists: T1 and T2. T1 follows the LRU
Expand Down Expand Up @@ -337,16 +337,18 @@ static inline void move_to_mru(cache_t *cache,

void *cache_get(cache_t *cache, uint32_t key)
{
if (!cache->capacity || hlist_empty(&cache->map->ht_list_head[HASH(key)]))
if (!cache->capacity ||
hlist_empty(&cache->map->ht_list_head[cache_hash(key)]))
return NULL;

#if RV32_HAS(ARC)
arc_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list)
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list,
arc_entry_t)
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list, arc_entry_t)
#endif
{
if (entry->key == key)
Expand Down Expand Up @@ -388,10 +390,11 @@ void *cache_get(cache_t *cache, uint32_t key)
#else /* !RV32_HAS(ARC) */
lfu_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list)
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list,
lfu_entry_t)
hlist_for_each_entry (entry, &cache->map->ht_list_head[cache_hash(key)],
ht_list, lfu_entry_t)
#endif
{
if (entry->key == key)
Expand Down Expand Up @@ -478,7 +481,8 @@ void *cache_put(cache_t *cache, uint32_t key, void *value)
list_add(&new_entry->list, cache->lists[LRU_ghost_list]);
cache->list_size[LRU_ghost_list]++;
}
hlist_add_head(&new_entry->ht_list, &cache->map->ht_list_head[HASH(key)]);
hlist_add_head(&new_entry->ht_list,
&cache->map->ht_list_head[cache_hash(key)]);

CACHE_ASSERT(cache);
#else /* !RV32_HAS(ARC) */
Expand All @@ -504,7 +508,8 @@ void *cache_put(cache_t *cache, uint32_t key, void *value)
new_entry->frequency = 0;
list_add(&new_entry->list, cache->lists[new_entry->frequency++]);
cache->list_size++;
hlist_add_head(&new_entry->ht_list, &cache->map->ht_list_head[HASH(key)]);
hlist_add_head(&new_entry->ht_list,
&cache->map->ht_list_head[cache_hash(key)]);
assert(cache->list_size <= cache->capacity);
#endif
return delete_value;
Expand Down
17 changes: 4 additions & 13 deletions src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,17 +277,8 @@ void rv_debug(riscv_t *rv)
}
#endif /* RV32_HAS(GDBSTUB) */

/* hash function is used when mapping address into the block map */
static inline uint32_t hash(size_t k)
{
k ^= k << 21;
k ^= k >> 17;
#if (SIZE_MAX > 0xFFFFFFFF)
k ^= k >> 35;
k ^= k >> 51;
#endif
return k;
}
/* hash function for the block map */
HASH_FUNC_IMPL(map_hash, BLOCK_MAP_CAPACITY_BITS, 1 << BLOCK_MAP_CAPACITY_BITS);

/* allocate a basic block */
static block_t *block_alloc(riscv_t *rv)
Expand All @@ -304,7 +295,7 @@ static void block_insert(block_map_t *map, const block_t *block)
{
assert(map && block);
const uint32_t mask = map->block_capacity - 1;
uint32_t index = hash(block->pc_start);
uint32_t index = map_hash(block->pc_start);

/* insert into the block map */
for (;; index++) {
Expand All @@ -320,7 +311,7 @@ static void block_insert(block_map_t *map, const block_t *block)
static block_t *block_find(const block_map_t *map, const uint32_t addr)
{
assert(map);
uint32_t index = hash(addr);
uint32_t index = map_hash(addr);
const uint32_t mask = map->block_capacity - 1;

/* find block in block map */
Expand Down
1 change: 0 additions & 1 deletion src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "riscv_private.h"
#include "state.h"

#define BLOCK_MAP_CAPACITY_BITS 10
#define BLOCK_IR_MAP_CAPACITY_BITS 10

/* initialize the block map */
Expand Down
2 changes: 2 additions & 0 deletions src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ enum {
#define MSTATUS_MPIE (1 << MSTATUS_MPIE_SHIFT)
#define MSTATUS_MPP (3 << MSTATUS_MPP_SHIFT)

#define BLOCK_MAP_CAPACITY_BITS 10

/* forward declaration for internal structure */
typedef struct riscv_internal riscv_t;
typedef void *riscv_user_t;
Expand Down
11 changes: 11 additions & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,14 @@ void rv_gettimeofday(struct timeval *tv);

/* Retrieve the value used by a clock which is specified by clock_id. */
void rv_clock_gettime(struct timespec *tp);

/* This hashing routine is adapted from Linux kernel.
* See
* https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/hash.h
*/
#define HASH_FUNC_IMPL(name, size_bits, size) \
FORCE_INLINE uint32_t name(uint32_t val) \
{ \
/* 0x61C88647 is 32-bit golden ratio */ \
return (val * 0x61C88647 >> (32 - size_bits)) & ((size) -1); \
}

0 comments on commit c6e7e66

Please sign in to comment.