Restructuring

This commit is contained in:
Michael Zohner 2015-06-11 15:07:00 +02:00
parent 33fa67b6d5
commit e2ed7a0f11
6 changed files with 0 additions and 577 deletions

View File

@ -1,237 +0,0 @@
/*
* cuckoo.cpp
*
* Created on: Oct 7, 2014
* Author: mzohner
*/
#include "cuckoo.h"
//returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements
#ifndef TEST_UTILIZATION
uint8_t*
#else
uint32_t
#endif
cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitlen, uint32_t *outbitlen, uint32_t* nelesinbin,
uint32_t* perm, uint32_t ntasks, prf_state_ctx* prf_state)
{
//The resulting hash table
uint8_t* hash_table;
#ifdef DOUBLE_TABLE
cuckoo_entry_ctx*** cuckoo_table;
#else
cuckoo_entry_ctx** cuckoo_table;
#endif
cuckoo_entry_ctx* cuckoo_entries;
uint32_t i, j;
uint32_t *perm_ptr;
pthread_t* entry_gen_tasks;
cuckoo_entry_gen_ctx* ctx;
hs_t hs;
#ifdef COUNT_FAILS
uint32_t fails = 0;
#endif
init_hashing_state(&hs, neles, bitlen, nbins, prf_state);
*outbitlen = hs.outbitlen;
#ifdef DOUBLE_TABLE
cuckoo_table = (cuckoo_entry_ctx***) calloc(2, sizeof(cuckoo_entry_ctx**));
cuckoo_table[0] = (cuckoo_entry_ctx**) calloc(nbins, sizeof(cuckoo_entry_ctx*));
cuckoo_table[1] = (cuckoo_entry_ctx**) calloc(nbins, sizeof(cuckoo_entry_ctx*));
#else
cuckoo_table = (cuckoo_entry_ctx**) calloc(nbins, sizeof(cuckoo_entry_ctx*));
#endif
cuckoo_entries = (cuckoo_entry_ctx*) malloc(neles * sizeof(cuckoo_entry_ctx));
entry_gen_tasks = (pthread_t*) malloc(sizeof(pthread_t) * ntasks);
ctx = (cuckoo_entry_gen_ctx*) malloc(sizeof(cuckoo_entry_gen_ctx) * ntasks);
#ifndef TEST_UTILIZATION
for(i = 0; i < ntasks; i++) {
ctx[i].elements = elements;
ctx[i].cuckoo_entries = cuckoo_entries;
ctx[i].hs = &hs;
ctx[i].startpos = i * ceil_divide(neles, ntasks);
ctx[i].endpos = min(ctx[i].startpos + ceil_divide(neles, ntasks), neles);
//cout << "Thread " << i << " starting from " << ctx[i].startpos << " going to " << ctx[i].endpos << " for " << neles << " elements" << endl;
if(pthread_create(entry_gen_tasks+i, NULL, gen_cuckoo_entries, (void*) (ctx+i))) {
cerr << "Error in creating new pthread at cuckoo hashing!" << endl;
exit(0);
}
}
for(i = 0; i < ntasks; i++) {
if(pthread_join(entry_gen_tasks[i], NULL)) {
cerr << "Error in joining pthread at cuckoo hashing!" << endl;
exit(0);
}
}
#else
ctx[0].elements = elements;
ctx[0].cuckoo_entries = cuckoo_entries;
ctx[0].hs = &hs;
ctx[0].startpos = 0;
ctx[0].endpos = neles;
gen_cuckoo_entries(ctx);
#endif
//for(i = 0; i < nbins; i++) {
// cout << "Address " << i << " mapped to " << hs.address_used[i] << " times" << endl;
//}
//insert all elements into the cuckoo hash table
for(i = 0; i < neles; i++) {
if(!(insert_element(cuckoo_table, cuckoo_entries + i, neles))) {
#ifdef COUNT_FAILS
fails++;
/*cout << "insertion failed for element " << (hex) << (*(((uint32_t*) elements)+i)) << ", inserting to address: ";
for(uint32_t j = 0; j < NUM_HASH_FUNCTIONS; j++) {
cout << (cuckoo_entries + i)->address[j] << ", ";
}
cout << (dec) << endl;*/
#else
cerr << "Insertion not successful for element " <<i <<"!" << endl;
exit(0);
#endif
}
}
//Copy the final state of the cuckoo table into the hash table
perm_ptr = perm;
#ifndef TEST_UTILIZATION
hash_table = (uint8_t*) calloc(nbins, hs.outbytelen);
for(i = 0; i < nbins; i++) {
if(cuckoo_table[i] != NULL) {
memcpy(hash_table + i * hs.outbytelen, cuckoo_table[i]->val, hs.outbytelen);
//cout << "copying value: " << (hex) << (unsigned int) cuckoo_table[i]->val[cuckoo_table[i]->pos][0] << (dec) << endl;
*perm_ptr = cuckoo_table[i]->eleid;
perm_ptr++;
nelesinbin[i] = 1;
} else {
memset(hash_table + i * hs.outbytelen, DUMMY_ENTRY_CLIENT, hs.outbytelen);
nelesinbin[i] = 0;
}
}
#endif
#ifndef TEST_UTILIZATION
//Cleanup
for(i = 0; i < neles; i++) {
free(cuckoo_entries[i].val);
}
#endif
free(cuckoo_entries);
#ifdef DOUBLE_TABLE
free(cuckoo_table[0]);
free(cuckoo_table[1]);
#else
free(cuckoo_table);
#endif
free(entry_gen_tasks);
free(ctx);
free_hashing_state(&hs);
#ifdef TEST_UTILIZATION
return fails;
#else
return hash_table;
#endif
}
void *gen_cuckoo_entries(void *ctx_void) {
cuckoo_entry_gen_ctx* ctx = (cuckoo_entry_gen_ctx*) ctx_void;
hs_t* hs = ctx->hs;
uint32_t i, inbytelen = ceil_divide(hs->inbitlen, 8);
uint8_t* eleptr = ctx->elements + inbytelen * ctx->startpos;
//generate the cuckoo entries for all elements
for(i = ctx->startpos; i < ctx->endpos; i++, eleptr+=inbytelen) {
gen_cuckoo_entry(eleptr, ctx->cuckoo_entries + i, hs, i);
}
}
inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint32_t ele_id) {
uint32_t i;
out->pos = 0;
out->eleid = ele_id;
#ifndef TEST_UTILIZATION
out->val = (uint8_t*) calloc(hs->outbytelen, sizeof(uint8_t));
#endif
hashElement(in, out->address, out->val, hs);
}
#ifdef DOUBLE_TABLE
inline bool insert_element(cuckoo_entry_ctx*** ctable, cuckoo_entry_ctx* element, uint32_t max_iterations) {
#else
inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element, uint32_t max_iterations) {
#endif
cuckoo_entry_ctx *evicted, *tmp_evicted;
uint32_t i, ev_pos, iter_cnt;
#ifdef DEBUG_CUCKOO
cout << "iter_cnt = " << iter_cnt << " for element " << (hex) << (*((uint32_t*) element->element)) << (dec) << ", inserting to address: "
<< element->address[element->pos] << " or " << element->address[element->pos^1] << endl;
#endif
for(iter_cnt = 0, evicted = element; iter_cnt < max_iterations; iter_cnt++) {
//TODO: assert(addr < MAX_TAB_ENTRIES)
for(i = 0; i < NUM_HASH_FUNCTIONS; i++) {//, ele_pos=(ele_pos+1)%NUM_HASH_FUNCTIONS) {
#ifdef DOUBLE_TABLE
if(ctable[i][evicted->address[i]] == NULL) {
ctable[i][evicted->address[i]] = evicted;
evicted->pos = i;
return true;
}
#else
if(ctable[evicted->address[i]] == NULL) {
ctable[evicted->address[i]] = evicted;
evicted->pos = i;
#ifdef TEST_CHAINLEN
chain_cnt[iter_cnt]++;
#endif
return true;
}
#endif
}
//choose random bin to evict other element
#if NUM_HASH_FUNCTIONS == 2
ev_pos = evicted->address[evicted->pos% NUM_HASH_FUNCTIONS];
#else
ev_pos = evicted->address[(evicted->pos^iter_cnt) % NUM_HASH_FUNCTIONS];
#endif
#ifdef DOUBLE_TABLE
tmp_evicted = ctable[evicted->pos][ev_pos];
ctable[evicted->pos][ev_pos] = evicted;
#else
tmp_evicted = ctable[ev_pos];
ctable[ev_pos] = evicted;
#endif
evicted = tmp_evicted;
//change position - if the number of HF's is increased beyond 2 this should be replaced by a different strategy
evicted->pos = (evicted->pos+1) % NUM_HASH_FUNCTIONS;
}
//the highest number of iterations has been reached
return false;
}
#ifdef TEST_CHAINLEN
void print_chain_cnt() {
//cout << "Chain Count: " << endl;
for(uint32_t i = 0; i < MAX_ITERATIONS; i++) {
//if(chain_cnt[i] > 0)
cout << i << "\t" << chain_cnt[i] << endl;
}
}
#endif

View File

@ -1,74 +0,0 @@
/*
* cuckoo.h
*
* Created on: Oct 7, 2014
* Author: mzohner
*/
#ifndef CUCKOO_H_
#define CUCKOO_H_
#include "hashing_util.h"
#define MAX_ITERATIONS 1024
//#define DEBUG_CUCKOO
#ifdef TEST_UTILIZATION
#define COUNT_FAILS
#endif
//#define DOUBLE_TABLE
//#define TEST_CHAINLEN
#ifdef TEST_CHAINLEN
static uint64_t chain_cnt[MAX_ITERATIONS];
void print_chain_cnt();
#endif
struct cuckoo_entry_ctx {
//id of the element in the source set
uint32_t eleid;
//addresses the bin of the cuckoo entry in the cuckoo table, will only work for up to 2^{32} bins
uint32_t address[NUM_HASH_FUNCTIONS];
//the value of the entry
uint8_t* val;
//which position is the entry currently mapped to
uint32_t pos;
#ifdef DEBUG_CUCKOO
uint8_t* element;
#endif
};
struct cuckoo_entry_gen_ctx {
//starting position in the generation process
uint32_t startpos;
//end position of entries that are generated by this thread
uint32_t endpos;
//input elements
uint8_t* elements;
//pointer to the cuckoo entries
cuckoo_entry_ctx* cuckoo_entries;
hs_t* hs;
};
//returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements
#ifndef TEST_UTILIZATION
uint8_t*
#else
uint32_t
#endif
cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitlen, uint32_t* outbitlen, uint32_t* nelesinbin,
uint32_t* perm, uint32_t ntasks, prf_state_ctx* prf_state);
//routine for generating the entries, is invoked by the threads
void *gen_cuckoo_entries(void *ctx);
inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint32_t ele_id);
#ifdef DOUBLE_TABLE
inline bool insert_element(cuckoo_entry_ctx*** ctable, cuckoo_entry_ctx* element, uint32_t max_iterations);
#else
inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element, uint32_t max_iterations);
#endif
#endif /* CUCKOO_H_ */

View File

@ -1,19 +0,0 @@
/*
* hashing_includes.h
*
* The purpose of this class is to abstract the included header files
* since the hashing source files are used as a submodule in another
* git project:
* https://github.com/encryptogroup/ABY/tree/public/src/examples/psi_phasing/common
*
* Created on: Jun 11, 2015
* Author: mzohner
*/
#ifndef HASHING_INCLUDES_H_
#define HASHING_INCLUDES_H_
#include "../util/typedefs.h"
#include "../util/crypto/crypto.h"
#endif /* HASHING_INCLUDES_H_ */

View File

@ -1,192 +0,0 @@
/*
* simple_hashing.cpp
*
* Created on: Oct 8, 2014
* Author: mzohner
*/
#include "simple_hashing.h"
uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint32_t *outbitlen, uint32_t* nelesinbin, uint32_t nbins,
uint32_t ntasks, prf_state_ctx* prf_state) {
sht_ctx* table;
//uint8_t** bin_content;
uint8_t *eleptr, *bin_ptr, *result, *res_bins;
uint32_t i, j, tmpneles;
sheg_ctx* ctx;
pthread_t* entry_gen_tasks;
hs_t hs;
init_hashing_state(&hs, neles, bitlen, nbins, prf_state);
//Set the output bit-length of the hashed elements
*outbitlen = hs.outbitlen;
entry_gen_tasks = (pthread_t*) malloc(sizeof(pthread_t) * ntasks);
ctx = (sheg_ctx*) malloc(sizeof(sheg_ctx) * ntasks);
table = (sht_ctx*) malloc(sizeof(sht_ctx) * ntasks);
for(i = 0; i < ntasks; i++) {
init_hash_table(table + i, ceil_divide(neles, ntasks), &hs);
}
//for(i = 0; i < nbins; i++)
// pthread_mutex_init(locks+i, NULL);
//tmpbuf = (uint8_t*) malloc(table->outbytelen);
for(i = 0; i < ntasks; i++) {
ctx[i].elements = elements;
ctx[i].table = table + i;
ctx[i].startpos = i * ceil_divide(neles, ntasks);
ctx[i].endpos = min(ctx[i].startpos + ceil_divide(neles, ntasks), neles);
ctx[i].hs = &hs;
//cout << "Thread " << i << " starting from " << ctx[i].startpos << " going to " << ctx[i].endpos << " for " << neles << " elements" << endl;
if(pthread_create(entry_gen_tasks+i, NULL, gen_entries, (void*) (ctx+i))) {
cerr << "Error in creating new pthread at simple hashing!" << endl;
exit(0);
}
}
for(i = 0; i < ntasks; i++) {
if(pthread_join(entry_gen_tasks[i], NULL)) {
cerr << "Error in joining pthread at simple hashing!" << endl;
exit(0);
}
}
//for(i = 0, eleptr=elements; i < neles; i++, eleptr+=inbytelen) {
// insert_element(table, eleptr, tmpbuf);
//}
//malloc and copy simple hash table into hash table
//bin_content = (uint8_t**) malloc(sizeof(uint8_t*) * nbins);
//*nelesinbin = (uint32_t*) malloc(sizeof(uint32_t) * nbins);
res_bins = (uint8_t*) malloc(neles * NUM_HASH_FUNCTIONS * hs.outbytelen);
bin_ptr = res_bins;
for(i = 0; i < hs.nbins; i++) {
nelesinbin[i] = 0;
for(j = 0; j < ntasks; j++) {
tmpneles = (table +j)->bins[i].nvals;
nelesinbin[i] += tmpneles;
//bin_content[i] = (uint8_t*) malloc(nelesinbin[i] * table->outbytelen);
memcpy(bin_ptr, (table + j)->bins[i].values, tmpneles * hs.outbytelen);
bin_ptr += (tmpneles * hs.outbytelen);
}
//right now only the number of elements in each bin is copied instead of the max bin size
}
for(j = 0; j < ntasks; j++)
free_hash_table(table + j);
free(table);
free(entry_gen_tasks);
free(ctx);
//for(i = 0; i < nbins; i++)
// pthread_mutex_destroy(locks+i);
//free(locks);
free_hashing_state(&hs);
return res_bins;
}
void *gen_entries(void *ctx_tmp) {
//Insert elements in parallel, use lock to communicate
uint8_t *tmpbuf, *eleptr;
sheg_ctx* ctx = (sheg_ctx*) ctx_tmp;
uint32_t i, inbytelen, *address;
address = (uint32_t*) malloc(NUM_HASH_FUNCTIONS * sizeof(uint32_t));
tmpbuf = (uint8_t*) calloc(ceil_divide(ctx->hs->outbitlen, 8), sizeof(uint8_t)); //for(i = 0; i < NUM_HASH_FUNCTIONS; i++) {
// tmpbuf[i] = (uint8_t*) malloc(ceil_divide(ctx->hs->outbitlen, 8));
//}
for(i = ctx->startpos, eleptr=ctx->elements, inbytelen=ctx->hs->inbytelen; i < ctx->endpos; i++, eleptr+=inbytelen) {
insert_element(ctx->table, eleptr, address, tmpbuf, ctx->hs);
}
free(tmpbuf);
free(address);
}
inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, uint8_t* tmpbuf, hs_t* hs) {
uint32_t i, j;
bin_ctx* tmp_bin;
hashElement(element, address, tmpbuf, hs);
for(i = 0; i < NUM_HASH_FUNCTIONS; i++) {
tmp_bin=table->bins + address[i];
//pthread_mutex_lock(locks + address[i]);
memcpy(tmp_bin->values + tmp_bin->nvals * hs->outbytelen, tmpbuf, hs->outbytelen);
for(j = 0; j < i; j++) {
if(address[i] == address[j]) {
memset(tmp_bin->values + tmp_bin->nvals * hs->outbytelen, DUMMY_ENTRY_SERVER, hs->outbytelen);
}
}
tmp_bin->nvals++;
//TODO: or simply allocate a bigger block of memory: table->maxbinsize * 2, left out for efficiency reasons
if(tmp_bin->nvals == table->maxbinsize) {
increase_max_bin_size(table, hs->outbytelen);
}
//assert(tmp_bin->nvals < table->maxbinsize);
/*cout << "Inserted into bin: " << address << ": " << (hex);
for(uint32_t j = 0; j < table->outbytelen; j++) {
cout << (unsigned int) tmpbuf[j];
}
cout << (dec) << endl;*/
//pthread_mutex_unlock(locks + address[i]);
}
}
void init_hash_table(sht_ctx* table, uint32_t nelements, hs_t* hs) {
uint32_t i;
//table->addrbitlen = ceil_log2(nbins);
//table->addrbytelen = ceil_divide(table->addrbitlen, 8);
//table->inbytelen = ceil_divide(inbitlen, 8);
if(ceil_divide(nelements, hs->nbins) < 3)
table->maxbinsize = 3*max(ceil_log2(nelements),3);
else
table->maxbinsize = 6*max((int) ceil_divide(nelements, hs->nbins), 3);
//cout << "maxbinsize = " << table->maxbinsize << endl;
//table->outbytelen = ceil_divide(getOutBitLen(inbitlen, nbins), 8);
table->nbins = hs->nbins;
table->bins = (bin_ctx*) calloc(hs->nbins, sizeof(bin_ctx));
for(i = 0; i < hs->nbins; i++) {
table->bins[i].values = (uint8_t*) malloc(table->maxbinsize * hs->outbytelen);
}
}
void free_hash_table(sht_ctx* table) {
uint32_t i;
//1. free the byte-pointers for the values in the bints
for(i = 0; i < table->nbins; i++) {
//if(table->bins[i].nvals > 0)
free(table->bins[i].values);
}
//2. free the bins
free(table->bins);
//3. free the actual table
//free(table);
}
void increase_max_bin_size(sht_ctx* table, uint32_t valbytelen) {
uint32_t new_maxsize = table->maxbinsize * 2;
uint8_t* tmpvals;
for(uint32_t i = 0; i < table->nbins; i++) {
tmpvals = table->bins[i].values;
table->bins[i].values = (uint8_t*) malloc(new_maxsize * valbytelen);
memcpy(table->bins[i].values, tmpvals, table->bins[i].nvals * valbytelen);
free(tmpvals);
}
table->maxbinsize = new_maxsize;
}

View File

@ -1,55 +0,0 @@
/*
* simle_hashing.h
*
* Created on: Oct 8, 2014
* Author: mzohner
*/
#ifndef SIMLE_HASHING_H_
#define SIMLE_HASHING_H_
#include "hashing_util.h"
struct bin_ctx {
//hash-values of all elements mapped to this bin
uint8_t* values;
//number of elements stored in this bin
uint32_t nvals;
};
typedef struct simple_hash_table_ctx {
//pointer to the bins in the hash table
bin_ctx* bins;
//number bins in the hash table
uint32_t nbins;
//max bin size
uint32_t maxbinsize;
//uint32_t addrbitlen;
//uint32_t addrbytelen;
//uint32_t inbytelen;
//uint32_t outbytelen;
} sht_ctx;
typedef struct simple_hash_entry_gen_ctx {
sht_ctx* table;
//input elements
uint8_t* elements;
uint32_t startpos;
uint32_t endpos;
//uint32_t inbytelen;
hs_t* hs;
} sheg_ctx;
//returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements
uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint32_t* outbitlen, uint32_t* nelesinbin, uint32_t nbins,
uint32_t ntasks, prf_state_ctx* prf_state);
//routine for generating the entries, is invoked by the threads
void *gen_entries(void *ctx);
void init_hash_table(sht_ctx* table, uint32_t nelements, hs_t* hs);
void increase_max_bin_size(sht_ctx* table, uint32_t valbytelen);
void free_hash_table(sht_ctx* table);
inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, uint8_t* tmpbuf, hs_t* hs);
#endif /* SIMLE_HASHING_H_ */