| … | … | @@ -105,6 +105,50 @@ int *compact_hash_init(int ncells, uint isize, uint jsize, uint report_level){ |
| 105 | 105 | for (uint ii = 0; ii<2*hashtablesize; ii+=2){ |
| 106 | 106 | hash[ii] = -1; |
| 107 | 107 | } |
| 108 | |
| 109 | if (hash_method == LINEAR){ |
| 110 | if (hash_report_level == 0){ |
| 111 | read_hash = read_hash_linear; |
| 112 | write_hash = write_hash_linear; |
| 113 | } else if (hash_report_level == 1){ |
| 114 | read_hash = read_hash_linear_report_level_1; |
| 115 | write_hash = write_hash_linear_report_level_1; |
| 116 | } else if (hash_report_level == 2){ |
| 117 | read_hash = read_hash_linear_report_level_2; |
| 118 | write_hash = write_hash_linear_report_level_2; |
| 119 | } else if (hash_report_level == 3){ |
| 120 | read_hash = read_hash_linear_report_level_3; |
| 121 | write_hash = write_hash_linear_report_level_3; |
| 122 | } |
| 123 | } else if (hash_method == QUADRATIC) { |
| 124 | if (hash_report_level == 0){ |
| 125 | read_hash = read_hash_quadratic; |
| 126 | write_hash = write_hash_quadratic; |
| 127 | } else if (hash_report_level == 1){ |
| 128 | read_hash = read_hash_quadratic_report_level_1; |
| 129 | write_hash = write_hash_quadratic_report_level_1; |
| 130 | } else if (hash_report_level == 2){ |
| 131 | read_hash = read_hash_quadratic_report_level_2; |
| 132 | write_hash = write_hash_quadratic_report_level_2; |
| 133 | } else if (hash_report_level == 3){ |
| 134 | read_hash = read_hash_quadratic_report_level_3; |
| 135 | write_hash = write_hash_quadratic_report_level_3; |
| 136 | } |
| 137 | } else if (hash_method == PRIME_JUMP) { |
| 138 | if (hash_report_level == 0){ |
| 139 | read_hash = read_hash_primejump; |
| 140 | write_hash = write_hash_primejump; |
| 141 | } else if (hash_report_level == 1){ |
| 142 | read_hash = read_hash_primejump_report_level_1; |
| 143 | write_hash = write_hash_primejump_report_level_1; |
| 144 | } else if (hash_report_level == 2){ |
| 145 | read_hash = read_hash_primejump_report_level_2; |
| 146 | write_hash = write_hash_primejump_report_level_2; |
| 147 | } else if (hash_report_level == 3){ |
| 148 | read_hash = read_hash_primejump_report_level_3; |
| 149 | write_hash = write_hash_primejump_report_level_3; |
| 150 | } |
| 151 | } |
| 108 | 152 | } else { |
| 109 | 153 | hashtablesize = perfect_hash_size; |
| 110 | 154 | |
| … | … | @@ -112,6 +156,9 @@ int *compact_hash_init(int ncells, uint isize, uint jsize, uint report_level){ |
| 112 | 156 | for (uint ii = 0; ii<hashtablesize; ii++){ |
| 113 | 157 | hash[ii] = -1; |
| 114 | 158 | } |
| 159 | |
| 160 | read_hash = read_hash_perfect; |
| 161 | write_hash = write_hash_perfect; |
| 115 | 162 | } |
| 116 | 163 | |
| 117 | 164 | if (hash_report_level >= 2) { |
| … | … | @@ -120,55 +167,137 @@ int *compact_hash_init(int ncells, uint isize, uint jsize, uint report_level){ |
| 120 | 167 | (double)hashtablesize/(double)(isize*jsize)); |
| 121 | 168 | } |
| 122 | 169 | |
| 123 | | if (! do_compact_hash) { |
| 124 | | read_hash = read_hash_perfect; |
| 125 | | write_hash = write_hash_perfect; |
| 126 | | } else if (hash_method == LINEAR){ |
| 127 | | if (hash_report_level == 0){ |
| 128 | | read_hash = read_hash_linear; |
| 129 | | write_hash = write_hash_linear; |
| 130 | | } else if (hash_report_level == 1){ |
| 131 | | read_hash = read_hash_linear_report_level_1; |
| 132 | | write_hash = write_hash_linear_report_level_1; |
| 133 | | } else if (hash_report_level == 2){ |
| 134 | | read_hash = read_hash_linear_report_level_2; |
| 135 | | write_hash = write_hash_linear_report_level_2; |
| 136 | | } else if (hash_report_level == 3){ |
| 137 | | read_hash = read_hash_linear_report_level_3; |
| 138 | | write_hash = write_hash_linear_report_level_3; |
| 170 | return(hash); |
| 171 | } |
| 172 | |
| 173 | #ifdef _OPENMP |
| 174 | |
| 175 | #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 |
| 176 | int *compact_hash_init_openmp(int ncells, uint isize, uint jsize, uint report_level){ |
| 177 | #else |
| 178 | int *compact_hash_init_openmp(int ncells, uint isize, uint jsize, uint report_level, omp_lock_t **lock){ |
| 179 | #endif |
| 180 | |
| 181 | hash_ncells = 0; |
| 182 | write_hash_collisions = 0; |
| 183 | read_hash_collisions = 0; |
| 184 | hash_queries = 0; |
| 185 | hash_report_level = report_level; |
| 186 | hash_stride = isize; |
| 187 | int *hash = NULL; |
| 188 | |
| 189 | if (choose_hash_method != METHOD_UNSET) hash_method = choose_hash_method; |
| 190 | |
| 191 | uint compact_hash_size = (uint)((double)ncells*hash_mult); |
| 192 | uint perfect_hash_size = (uint)(isize*jsize); |
| 193 | |
| 194 | if (hash_method == METHOD_UNSET){ |
| 195 | float hash_mem_factor = 20.0; |
| 196 | float hash_mem_ratio = (double)perfect_hash_size/(double)compact_hash_size; |
| 197 | if (mem_opt_factor != 1.0) hash_mem_factor /= (mem_opt_factor*0.2); |
| 198 | hash_method = (hash_mem_ratio < hash_mem_factor) ? PERFECT_HASH : QUADRATIC; |
| 199 | //hash_method = QUADRATIC; |
| 200 | |
| 201 | if (hash_report_level >= 2) printf("DEBUG hash_method %d hash_mem_ratio %f hash_mem_factor %f mem_opt_factor %f perfect_hash_size %u compact_hash_size %u\n", |
| 202 | hash_method,hash_mem_ratio,hash_mem_factor,mem_opt_factor,perfect_hash_size,compact_hash_size); |
| 203 | } |
| 204 | |
| 205 | int do_compact_hash = (hash_method == PERFECT_HASH) ? 0 : 1; |
| 206 | |
| 207 | if (hash_report_level >= 2) printf("DEBUG do_compact_hash %d hash_method %d perfect_hash_size %u compact_hash_size %u\n", |
| 208 | do_compact_hash,hash_method,perfect_hash_size,compact_hash_size); |
| 209 | |
| 210 | if (do_compact_hash) { |
| 211 | hashtablesize = compact_hash_size; |
| 212 | //srand48(0); |
| 213 | AA = (ulong)(1.0+(double)(prime-1)*drand48()); |
| 214 | BB = (ulong)(0.0+(double)(prime-1)*drand48()); |
| 215 | if (AA > prime-1 || BB > prime-1) exit(0); |
| 216 | if (hash_report_level > 1) printf("Factors AA %lu BB %lu\n",AA,BB); |
| 217 | |
| 218 | hash = (int *)genvector(2*hashtablesize,sizeof(int)); |
| 219 | |
| 220 | #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 |
| 221 | (*lock) = (omp_lock_t *)malloc(hashtablesize*sizeof(omp_lock_t)); |
| 222 | #endif |
| 223 | |
| 224 | #ifdef _OPENMP |
| 225 | #pragma omp parallel for |
| 226 | #endif |
| 227 | for (uint ii = 0; ii<hashtablesize; ii++){ |
| 228 | hash[2*ii] = -1; |
| 229 | #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 |
| 230 | omp_init_lock(&((*lock)[ii])); |
| 231 | #endif |
| 139 | 232 | } |
| 140 | | } else if (hash_method == QUADRATIC){ |
| 141 | | if (hash_report_level == 0){ |
| 142 | | read_hash = read_hash_quadratic; |
| 143 | | write_hash = write_hash_quadratic; |
| 144 | | } else if (hash_report_level == 1){ |
| 145 | | read_hash = read_hash_quadratic_report_level_1; |
| 146 | | write_hash = write_hash_quadratic_report_level_1; |
| 147 | | } else if (hash_report_level == 2){ |
| 148 | | read_hash = read_hash_quadratic_report_level_2; |
| 149 | | write_hash = write_hash_quadratic_report_level_2; |
| 150 | | } else if (hash_report_level == 3){ |
| 151 | | read_hash = read_hash_quadratic_report_level_3; |
| 152 | | write_hash = write_hash_quadratic_report_level_3; |
| 233 | |
| 234 | if (hash_method == LINEAR){ |
| 235 | if (hash_report_level == 0){ |
| 236 | read_hash = read_hash_linear; |
| 237 | write_hash_openmp = write_hash_linear_openmp; |
| 238 | } else if (hash_report_level == 1){ |
| 239 | read_hash = read_hash_linear_report_level_1; |
| 240 | write_hash_openmp = write_hash_linear_openmp_report_level_1; |
| 241 | } else if (hash_report_level == 2){ |
| 242 | read_hash = read_hash_linear_report_level_2; |
| 243 | write_hash_openmp = write_hash_linear_openmp_report_level_2; |
| 244 | } else if (hash_report_level == 3){ |
| 245 | read_hash = read_hash_linear_report_level_3; |
| 246 | write_hash_openmp = write_hash_linear_openmp_report_level_3; |
| 247 | } |
| 248 | } else if (hash_method == QUADRATIC) { |
| 249 | if (hash_report_level == 0){ |
| 250 | read_hash = read_hash_quadratic; |
| 251 | write_hash_openmp = write_hash_quadratic_openmp; |
| 252 | } else if (hash_report_level == 1){ |
| 253 | read_hash = read_hash_quadratic_report_level_1; |
| 254 | write_hash_openmp = write_hash_quadratic_openmp_report_level_1; |
| 255 | } else if (hash_report_level == 2){ |
| 256 | read_hash = read_hash_quadratic_report_level_2; |
| 257 | write_hash_openmp = write_hash_quadratic_openmp_report_level_2; |
| 258 | } else if (hash_report_level == 3){ |
| 259 | read_hash = read_hash_quadratic_report_level_3; |
| 260 | write_hash_openmp = write_hash_quadratic_openmp_report_level_3; |
| 261 | } |
| 262 | } else if (hash_method == PRIME_JUMP) { |
| 263 | if (hash_report_level == 0){ |
| 264 | read_hash = read_hash_primejump; |
| 265 | write_hash_openmp = write_hash_primejump_openmp; |
| 266 | } else if (hash_report_level == 1){ |
| 267 | read_hash = read_hash_primejump_report_level_1; |
| 268 | write_hash_openmp = write_hash_primejump_openmp_report_level_1; |
| 269 | } else if (hash_report_level == 2){ |
| 270 | read_hash = read_hash_primejump_report_level_2; |
| 271 | write_hash_openmp = write_hash_primejump_openmp_report_level_2; |
| 272 | } else if (hash_report_level == 3){ |
| 273 | read_hash = read_hash_primejump_report_level_3; |
| 274 | write_hash_openmp = write_hash_primejump_openmp_report_level_3; |
| 275 | } |
| 153 | 276 | } |
| 154 | | } else if (hash_method == PRIME_JUMP){ |
| 155 | | if (hash_report_level == 0){ |
| 156 | | read_hash = read_hash_primejump; |
| 157 | | write_hash = write_hash_primejump; |
| 158 | | } else if (hash_report_level == 1){ |
| 159 | | read_hash = read_hash_primejump_report_level_1; |
| 160 | | write_hash = write_hash_primejump_report_level_1; |
| 161 | | } else if (hash_report_level == 2){ |
| 162 | | read_hash = read_hash_primejump_report_level_2; |
| 163 | | write_hash = write_hash_primejump_report_level_2; |
| 164 | | } else if (hash_report_level == 3){ |
| 165 | | read_hash = read_hash_primejump_report_level_3; |
| 166 | | write_hash = write_hash_primejump_report_level_3; |
| 277 | } else { |
| 278 | hashtablesize = perfect_hash_size; |
| 279 | |
| 280 | hash = (int *)genvector(hashtablesize,sizeof(int)); |
| 281 | #ifdef _OPENMP |
| 282 | #pragma omp parallel for |
| 283 | #endif |
| 284 | for (uint ii = 0; ii<hashtablesize; ii++){ |
| 285 | hash[ii] = -1; |
| 167 | 286 | } |
| 287 | |
| 288 | read_hash = read_hash_perfect; |
| 289 | write_hash_openmp = write_hash_perfect_openmp; |
| 290 | } |
| 291 | |
| 292 | if (hash_report_level >= 2) { |
| 293 | printf("Hash table size %u perfect hash table size %u memory savings %d by percentage %lf\n", |
| 294 | hashtablesize,isize*jsize,(int)isize*(int)jsize-(int)hashtablesize, |
| 295 | (double)hashtablesize/(double)(isize*jsize) * 100.0); |
| 168 | 296 | } |
| 169 | 297 | |
| 170 | 298 | return(hash); |
| 171 | 299 | } |
| 300 | #endif |
| 172 | 301 | |
| 173 | 302 | void write_hash_perfect(uint ic, ulong hashkey, int *hash){ |
| 174 | 303 | hash[hashkey] = ic; |
| … | … | @@ -1105,9 +1234,31 @@ int read_hash_primejump_report_level_3(ulong hashkey, int *hash){ |
| 1105 | 1234 | } |
| 1106 | 1235 | |
| 1107 | 1236 | void compact_hash_delete(int *hash){ |
| 1108 | | free(hash); |
| 1237 | read_hash = NULL; |
| 1238 | free(hash); |
| 1109 | 1239 | } |
| 1110 | 1240 | |
| 1241 | #ifdef _OPENMP |
| 1242 | #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 |
| 1243 | void compact_hash_delete_openmp(int *hash){ |
| 1244 | #else |
| 1245 | void compact_hash_delete_openmp(int *hash, omp_lock_t *lock){ |
| 1246 | #endif |
| 1247 | |
| 1248 | read_hash = NULL; |
| 1249 | genvectorfree((void *)hash); |
| 1250 | #ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 |
| 1251 | if (hash_method != PERFECT_HASH){ |
| 1252 | for (uint i = 0; i<hashtablesize; i++){ |
| 1253 | omp_destroy_lock(&(lock[i])); |
| 1254 | } |
| 1255 | free(lock); |
| 1256 | } |
| 1257 | #endif |
| 1258 | hash_method = METHOD_UNSET; |
| 1259 | } |
| 1260 | #endif |
| 1261 | |
| 1111 | 1262 | void write_hash_collision_report(void){ |
| 1112 | 1263 | if (hash_method == PERFECT_HASH) return; |
| 1113 | 1264 | if (hash_report_level == 1) { |
| … | … | @@ -1131,6 +1282,7 @@ void read_hash_collision_report(void){ |
| 1131 | 1282 | } |
| 1132 | 1283 | |
| 1133 | 1284 | void final_hash_collision_report(void){ |
| 1285 | |
| 1134 | 1286 | if (hash_report_level >= 1 && read_hash_collisions_count > 0) { |
| 1135 | 1287 | printf("Final hash collision report -- write/read collisions per cell %lf/%lf\n",write_hash_collisions_runsum/(double)write_hash_collisions_count,read_hash_collisions_runsum/(double)read_hash_collisions_count); |
| 1136 | 1288 | } |