RAW (can-fail) flags for optimization and non-failing implementation added
This commit is contained in:
parent
418c8d289c
commit
4e4c266632
2
main.cpp
2
main.cpp
@ -135,7 +135,7 @@ int main() {
|
|||||||
test_basics(unomap, &umi);
|
test_basics(unomap, &umi);
|
||||||
|
|
||||||
/* Performance tests */
|
/* Performance tests */
|
||||||
int i = 100;
|
int i = 10000;
|
||||||
keystore(i, true);
|
keystore(i, true);
|
||||||
datastore(i, true);
|
datastore(i, true);
|
||||||
|
|
||||||
|
62
simap.h
62
simap.h
@ -7,8 +7,18 @@
|
|||||||
#include "amap.h"
|
#include "amap.h"
|
||||||
#include "arena.h/arena.h"
|
#include "arena.h/arena.h"
|
||||||
|
|
||||||
|
/* Possible optimizations, but they mean there can be lookup / insert errors (very rarely)
|
||||||
|
*/
|
||||||
|
#define SIMAP_AVX2_RAW
|
||||||
|
#define SIMAP_RAW
|
||||||
|
|
||||||
/* Perf trickery */
|
/* Perf trickery */
|
||||||
|
|
||||||
|
/* This unifies the ifdefs but separates code paths when needed */
|
||||||
|
#ifdef SIMAP_AVX2_RAW
|
||||||
|
#define SIMAP_RAW
|
||||||
|
#endif
|
||||||
|
|
||||||
/* I have no idea what MSVC has instead... */
|
/* I have no idea what MSVC has instead... */
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define SM_THREAD_LOCAL __declspec(thread)
|
#define SM_THREAD_LOCAL __declspec(thread)
|
||||||
@ -41,6 +51,17 @@ union simap_ptr64 {
|
|||||||
};
|
};
|
||||||
typedef union simap_ptr64 simap_ptr64;
|
typedef union simap_ptr64 simap_ptr64;
|
||||||
|
|
||||||
|
struct elem_nonkey_prefix {
|
||||||
|
/** The value (ptr) */
|
||||||
|
simap_ptr64 value;
|
||||||
|
|
||||||
|
/** Previous element index from base (full offset) */
|
||||||
|
uint32_t previndex;
|
||||||
|
/** Next element index from base (full offset) */
|
||||||
|
uint32_t nextindex;
|
||||||
|
};
|
||||||
|
typedef struct elem_nonkey_prefix elem_nonkey_prefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The per-element storage layout
|
* The per-element storage layout
|
||||||
*
|
*
|
||||||
@ -61,15 +82,10 @@ typedef union simap_ptr64 simap_ptr64;
|
|||||||
* and if you want check extra validity by jumping back&forth in it.
|
* and if you want check extra validity by jumping back&forth in it.
|
||||||
*/
|
*/
|
||||||
struct elem_prefix {
|
struct elem_prefix {
|
||||||
/** The value (ptr) */
|
/** Value and meta-data - divisible by 8bytes */
|
||||||
simap_ptr64 value;
|
elem_nonkey_prefix nonkey_prefix;
|
||||||
|
|
||||||
/** Previous element index from base (full offset) */
|
/** The prefix of the key - divisible by 8bytes padded string after this (inlined) */
|
||||||
uint32_t previndex;
|
|
||||||
/** Next element index from base (full offset) */
|
|
||||||
uint32_t nextindex;
|
|
||||||
|
|
||||||
/** The prefix of the key */
|
|
||||||
simap_c64 key_prefix;
|
simap_c64 key_prefix;
|
||||||
};
|
};
|
||||||
typedef struct elem_prefix elem_prefix;
|
typedef struct elem_prefix elem_prefix;
|
||||||
@ -107,10 +123,24 @@ static inline simap_instance simap_create() {
|
|||||||
static inline void* simap(void *amap_instance, AMAP_OP op, const char *key, void *ptr);
|
static inline void* simap(void *amap_instance, AMAP_OP op, const char *key, void *ptr);
|
||||||
|
|
||||||
// TODO: We can possibly hand-optimise this with intrinsics maybe - but I hope autovectorization (does not seem to happen???)
|
// TODO: We can possibly hand-optimise this with intrinsics maybe - but I hope autovectorization (does not seem to happen???)
|
||||||
static inline SM_ALWAYS_INLINE auint64 *make_tipp(auint64 *tip, auint64 prefix, auint64 *end) {
|
static inline SM_ALWAYS_INLINE auint64 *make_tipp(auint64 *base, auint64 *tip, auint64 prefix, auint64 *end) {
|
||||||
#pragma GCC unroll 4
|
#ifdef SIMAP_AVX2_RAW
|
||||||
|
/* TODO: Implement */
|
||||||
|
#endif
|
||||||
|
#ifdef SIMAP_RAW
|
||||||
|
#pragma GCC unroll 16
|
||||||
while((++tip < end) && (*tip != prefix));
|
while((++tip < end) && (*tip != prefix));
|
||||||
return tip;
|
return tip;
|
||||||
|
#endif
|
||||||
|
/* XXX: This only works because of (***) because reading -1 tips makes tip >= end for sure here and back */
|
||||||
|
elem_nonkey_prefix *pre = (elem_nonkey_prefix *)((uint8_t *)tip - sizeof(elem_nonkey_prefix));
|
||||||
|
tip = (auint64 *) ((uint8_t *)base + pre->nextindex + sizeof(elem_nonkey_prefix));
|
||||||
|
#pragma GCC unroll 16
|
||||||
|
while((tip < end) && (*tip != prefix)) {
|
||||||
|
pre = (elem_nonkey_prefix *)((uint8_t *)tip - sizeof(elem_nonkey_prefix));
|
||||||
|
tip = (auint64 *) ((uint8_t *)base + pre->nextindex + sizeof(elem_nonkey_prefix));
|
||||||
|
}
|
||||||
|
return tip;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char *key) {
|
static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char *key) {
|
||||||
@ -128,8 +158,8 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
|
|||||||
/* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */
|
/* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */
|
||||||
auint64 *base = (auint64 *) (map->base);
|
auint64 *base = (auint64 *) (map->base);
|
||||||
auint64 *end = (auint64 *)((uint8_t *)base + (map->usage_end));
|
auint64 *end = (auint64 *)((uint8_t *)base + (map->usage_end));
|
||||||
auint64 *tipp = make_tipp(base, prefix.u64, end);
|
auint64 *tipp = make_tipp(base, base, prefix.u64, end);
|
||||||
while(tipp < end) {
|
while(tipp < end) { // XXX: (***)
|
||||||
|
|
||||||
/* Need detailed lookup, because found the prefix */
|
/* Need detailed lookup, because found the prefix */
|
||||||
assert((*tipp == prefix.u64));
|
assert((*tipp == prefix.u64));
|
||||||
@ -138,13 +168,14 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
|
|||||||
if(!is_smallkey) {
|
if(!is_smallkey) {
|
||||||
char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t));
|
char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t));
|
||||||
if(strcmp(keyremains, tippremains) != 0) {
|
if(strcmp(keyremains, tippremains) != 0) {
|
||||||
tipp = make_tipp(tipp, prefix.u64, end);
|
tipp = make_tipp(base, tipp, prefix.u64, end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2));
|
simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2));
|
||||||
|
|
||||||
|
#ifdef SIMAP_RAW
|
||||||
/* Check back & forth (jump validation) */
|
/* Check back & forth (jump validation) */
|
||||||
uint32_t previ = *((uint32_t *)(tipp - 1));
|
uint32_t previ = *((uint32_t *)(tipp - 1));
|
||||||
if(previ == (uint32_t) -1) {
|
if(previ == (uint32_t) -1) {
|
||||||
@ -160,9 +191,10 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
|
|||||||
+ sizeof(uint32_t));
|
+ sizeof(uint32_t));
|
||||||
|
|
||||||
if(retipp != tipp) {
|
if(retipp != tipp) {
|
||||||
tipp = make_tipp(tipp, prefix.u64, end);
|
tipp = make_tipp(base, tipp, prefix.u64, end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif /* SIMAP_RAW */
|
||||||
|
|
||||||
/* Can have the (statistically checked) pointer */
|
/* Can have the (statistically checked) pointer */
|
||||||
return ptr;
|
return ptr;
|
||||||
@ -229,7 +261,7 @@ static inline void *simap_force_add(simap_instance *map, const char *key, void *
|
|||||||
uint32_t *usprev = (uint32_t *)((uint8_t *)(map->base) + usi +
|
uint32_t *usprev = (uint32_t *)((uint8_t *)(map->base) + usi +
|
||||||
sizeof(simap_ptr64));
|
sizeof(simap_ptr64));
|
||||||
*usprev = previ;
|
*usprev = previ;
|
||||||
*(usprev + 1) = (uint32_t) -1;
|
*(usprev + 1) = (uint32_t) -1; /* XXX: (***): ensures the "not < end" here! */
|
||||||
|
|
||||||
/* 8byte: First 8 char */
|
/* 8byte: First 8 char */
|
||||||
simap_c64 *start_str = (simap_c64 *)(usprev + 2);
|
simap_c64 *start_str = (simap_c64 *)(usprev + 2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user