tried auto-vectorization and simpler codes but does not happen as it says: "missed: not vectorized: no vectype for stmt, scalar_type: auint64"
This commit is contained in:
parent
6c1adb1655
commit
1c41a4e106
4
main.cpp
4
main.cpp
@ -115,12 +115,12 @@ int main() {
|
|||||||
test_basics(mapmap, &mi);
|
test_basics(mapmap, &mi);
|
||||||
|
|
||||||
/* Performance tests */
|
/* Performance tests */
|
||||||
int i = 1000;
|
int i = 10000;
|
||||||
keystore(i, true);
|
keystore(i, true);
|
||||||
datastore(i, true);
|
datastore(i, true);
|
||||||
|
|
||||||
test_perf(simap, &si, i, "simap");
|
|
||||||
test_perf(mapmap, &mi, i, "std::map");
|
test_perf(mapmap, &mi, i, "std::map");
|
||||||
|
test_perf(simap, &si, i, "simap");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
6
makefile
6
makefile
@ -3,4 +3,8 @@ debug:
|
|||||||
release:
|
release:
|
||||||
g++ main.cpp -O2 -Wall -o main
|
g++ main.cpp -O2 -Wall -o main
|
||||||
release-native:
|
release-native:
|
||||||
g++ main.cpp -march=native -O3 -Wall -o main
|
g++ main.cpp -fopt-info-vec-missed -march=native -O3 -Wall -o main
|
||||||
|
release-avx2:
|
||||||
|
g++ main.cpp -fopt-info-vec-missed -mavx2 -O3 -Wall -o main
|
||||||
|
release-avx2-asm:
|
||||||
|
g++ main.cpp -S -fopt-info-vec-missed -masm=intel -mavx2 -O3 -Wall -o main
|
||||||
|
73
simap.h
73
simap.h
@ -25,6 +25,7 @@
|
|||||||
#define SM_NOINLINE __attribute__ ((noinline))
|
#define SM_NOINLINE __attribute__ ((noinline))
|
||||||
#define SM_ALWAYS_INLINE __attribute__ ((always_inline))
|
#define SM_ALWAYS_INLINE __attribute__ ((always_inline))
|
||||||
#endif
|
#endif
|
||||||
|
typedef uint64_t auint64 __attribute__ ((__aligned__(8)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A "peasantly" map data structure backed by arena.h - basically a toy data structure...
|
* A "peasantly" map data structure backed by arena.h - basically a toy data structure...
|
||||||
@ -61,7 +62,7 @@ struct simap_instance {
|
|||||||
uint32_t prev_usage_end; /* previous usage_end or -1 if no previous exists... in bytes!!! */
|
uint32_t prev_usage_end; /* previous usage_end or -1 if no previous exists... in bytes!!! */
|
||||||
uint32_t usage_end; /* in bytes!!! */
|
uint32_t usage_end; /* in bytes!!! */
|
||||||
/** see doc comment for layout and why uint64_t* is the type */
|
/** see doc comment for layout and why uint64_t* is the type */
|
||||||
uint64_t *base;
|
auint64 *base;
|
||||||
};
|
};
|
||||||
typedef struct simap_instance simap_instance;
|
typedef struct simap_instance simap_instance;
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ static inline simap_instance simap_create() {
|
|||||||
ret.end = 0;
|
ret.end = 0;
|
||||||
ret.prev_usage_end = (uint32_t) -1;
|
ret.prev_usage_end = (uint32_t) -1;
|
||||||
ret.usage_end = 0;
|
ret.usage_end = 0;
|
||||||
ret.base = ((uint64_t*) aralloc(&(ret.a), sizeof(uint64_t), sizeof(uint64_t), 1)) /* addr divisible by 8 */
|
ret.base = ((auint64*) aralloc(&(ret.a), sizeof(auint64), sizeof(auint64), 1)) /* addr divisible by 8 */
|
||||||
+ 1; /* First really addressible thing */
|
+ 1; /* First really addressible thing */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -81,17 +82,23 @@ static inline void* simap(void *amap_instance, AMAP_OP op, const char *key, void
|
|||||||
/** The first 8 characters are stored as uint64_t for fast checks */
|
/** The first 8 characters are stored as uint64_t for fast checks */
|
||||||
union simap_c64 {
|
union simap_c64 {
|
||||||
char str8[8];
|
char str8[8];
|
||||||
uint64_t u64;
|
auint64 u64;
|
||||||
};
|
};
|
||||||
typedef union simap_char64 simap_char64;
|
typedef union simap_char64 simap_char64;
|
||||||
|
|
||||||
/** This is to ensure 8byte storage of pointers (with possible padding) */
|
/** This is to ensure 8byte storage of pointers (with possible padding) */
|
||||||
union simap_ptr64 {
|
union simap_ptr64 {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
uint64_t u64;
|
auint64 u64;
|
||||||
};
|
};
|
||||||
typedef union simap_ptr64 simap_ptr64;
|
typedef union simap_ptr64 simap_ptr64;
|
||||||
|
|
||||||
|
// TODO: We can possibly hand-optimise this with intrinsics maybe - but I hope autovectorization
|
||||||
|
static inline SM_ALWAYS_INLINE auint64 *make_tipp(auint64 *tip, auint64 prefix, auint64 *end) {
|
||||||
|
while((tip < end) && (*tip != prefix)) ++tip;
|
||||||
|
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) {
|
||||||
/* Construct prefix (fast-key) */
|
/* Construct prefix (fast-key) */
|
||||||
size_t keylen = strlen(key);
|
size_t keylen = strlen(key);
|
||||||
@ -107,43 +114,45 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
|
|||||||
/* TODO: Maybe this is buggy when we access behind our own data? */
|
/* TODO: Maybe this is buggy when we access behind our own data? */
|
||||||
/* TODO: Maybe I should create separate function for fast-lookup returning "next" pointer from a pointer to autovectorize? */
|
/* TODO: Maybe I should create separate function for fast-lookup returning "next" pointer from a pointer to autovectorize? */
|
||||||
/* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */
|
/* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */
|
||||||
uint64_t *base = map->base;
|
auint64 *base = map->base;
|
||||||
uint64_t *tipp = map->base;
|
auint64 *end = (auint64 *)((uint8_t *)base + (map->usage_end));
|
||||||
for(uint32_t i = 0; i < map->usage_end / 8; ++i, ++tipp) {
|
auint64 *tipp = make_tipp(map->base, prefix.u64, end);
|
||||||
/* Fast lookup */
|
while(tipp < end) {
|
||||||
if((*tipp == prefix.u64)) {
|
/* Fast lookup, because found prefix */
|
||||||
/* First check the remains of the string (only if needed) */
|
assert((*tipp == prefix.u64));
|
||||||
if(!is_smallkey) {
|
|
||||||
char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t));
|
/* First check the remains of the string (only if needed) */
|
||||||
if(strcmp(keyremains, tippremains) != 0) {
|
if(!is_smallkey) {
|
||||||
continue;
|
char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t));
|
||||||
}
|
if(strcmp(keyremains, tippremains) != 0) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2));
|
simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2));
|
||||||
|
|
||||||
/* 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) {
|
||||||
/* Expect it be good if it was first insert ever? Statistically rare to be not like it */
|
/* Expect it be good if it was first insert ever? Statistically rare to be not like it */
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
uint32_t prevnexi = *(uint32_t *)(((uint8_t *)base) + previ
|
uint32_t prevnexi = *(uint32_t *)(((uint8_t *)base) + previ
|
||||||
+ sizeof(simap_ptr64)
|
+ sizeof(simap_ptr64)
|
||||||
+ sizeof(uint32_t));
|
+ sizeof(uint32_t));
|
||||||
|
|
||||||
uint64_t *retipp = (uint64_t *)(((uint8_t *)base + prevnexi)
|
auint64 *retipp = (auint64 *)(((uint8_t *)base + prevnexi)
|
||||||
+ sizeof(simap_ptr64) + sizeof(uint32_t) +
|
+ sizeof(simap_ptr64) + sizeof(uint32_t) +
|
||||||
+ sizeof(uint32_t));
|
+ sizeof(uint32_t));
|
||||||
|
|
||||||
if(retipp != tipp) {
|
if(retipp != tipp) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* Can have the (statistically checked) pointer */
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Can have the (statistically checked) pointer */
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
tipp = make_tipp(map->base, prefix.u64, end);
|
||||||
|
|
||||||
/* Haven't found anything */
|
/* Haven't found anything */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user