// Builds the tree index. // k = number of keys, levels_n = number of levels, fanouts = array of fanouts for each level RangeIndex build_index(int k, int levels_n, int *fanouts){ RangeIndex range_index; // Initialize an array to store how large each level should be int* level_sizes = malloc(levels_n * sizeof(int)); for(int l = 0; l<levels_n; l++){ level_sizes[l] = 0; } // Find size of each level int key = 0; int should_do[levels_n]; for(int l=0; l<levels_n; l++){ should_do[l] = 1; } int current = levels_n - 1; while(key < k){ while(should_do[current] == 0){ current -= 1; } // if there are still keys left over and tree is full, report error. if(current < 0){ printf("Error: Too many build keys! \n"); free(level_sizes); range_index.didFail = 1; return range_index; } level_sizes[current]++; for(int reset=levels_n-1; reset > current; reset--){ should_do[reset] = 1; } if(level_sizes[current] % (fanouts[current] - 1 ) == 0){ should_do[current] = 0; } current = levels_n - 1; key++; } // Find padding for each level for(int i=0; i < levels_n; i++){ printf("levels[%d] = %d\n", i, level_sizes[i]); level_sizes[i] += (level_sizes[i] % (fanouts[i]-1)); } // If root node is empty, there are too few keys and an error should be reported. if (level_sizes[0] == 0) { printf("Error: Too few build keys! \n"); free(level_sizes); range_index.didFail = 1; return range_index; } // Create index int32_t **index = malloc(sizeof(int32_t *)*levels_n); void *ptr; for(int i=0; i<levels_n; i++){ if(posix_memalign(&ptr, 16, sizeof(int32_t ) * level_sizes[i]) != 0){ printf("Failed to allocate memory\n"); range_index.didFail = 1; return range_index; } index[i] = ptr; } // Hold a count of how many keys we've added for each level int level_counts[levels_n]; for(int i=0; i<levels_n; i++){ level_counts[i] = 0; //initialize } key = 0; for(int l=0; l<levels_n; l++){ should_do[l] = 1; } // Generate k random keys rand32_t *gen = rand32_init(time(NULL)); int32_t *keys = generate_sorted_unique(k, gen); free(gen); current = levels_n - 1; int32_t *level; // Initialze to MAX INT for(int i=0; i<levels_n; i++){ level = index[i]; for(int j=0; j<level_sizes[i]; j++){ level[j] = INT_MAX; } } // Insert keys while(key < k){ while(should_do[current] == 0){ current -= 1; } level = index[current]; level[level_counts[current]] = keys[key]; level_counts[current]++; for(int reset=levels_n-1; reset > current; reset--){ should_do[reset] = 1; } // If node full if(level_counts[current] % (fanouts[current] - 1 ) == 0){ should_do[current] = 0; } current = levels_n - 1; key++; } // Clean up and return free(keys); range_index.index = index; range_index.level_sizes = level_sizes; return range_index; }
int main(int argc, char* argv[]) { // parsing arguments assert(argc > 3); size_t num_keys = strtoull(argv[1], NULL, 0); size_t num_probes = strtoull(argv[2], NULL, 0); size_t num_levels = (size_t) argc - 3; size_t* fanout = malloc(sizeof(size_t) * num_levels); assert(fanout != NULL); for (size_t i = 0; i < num_levels; ++i) { fanout[i] = strtoull(argv[i + 3], NULL, 0); assert(fanout[i] >= 2 && fanout[i] <= 17); } // building the tree index rand32_t* gen = rand32_init((uint32_t) time(NULL)); assert(gen != NULL); int32_t* delimiter = generate_sorted_unique(num_keys, gen); assert(delimiter != NULL); Tree* tree = build_index(num_levels, fanout, num_keys, delimiter); free(delimiter); free(fanout); if (tree == NULL) { free(gen); exit(EXIT_FAILURE); } // generate probes int32_t* probe = generate(num_probes, gen); assert(probe != NULL); free(gen); uint32_t* result = malloc(sizeof(uint32_t) * num_probes); uint32_t* result1 = malloc(sizeof(uint32_t) * num_probes); uint32_t* result2 = malloc(sizeof(uint32_t) * num_probes); assert(result != NULL); // perform index probing (Phase 2) struct timeval stop_1, stop_2, start_1, start_2, start_3, stop_3; gettimeofday(&start_1, NULL); for (size_t i = 0; i < num_probes; ++i) { result[i] = probe_index(tree, probe[i]); } gettimeofday(&stop_1, NULL); gettimeofday(&start_2, NULL); for (size_t i = 0; i < num_probes; ++i) { result1[i] = probe_index_sse(tree,probe[i]); } gettimeofday(&stop_2, NULL); gettimeofday(&start_3, NULL); int flag=0; if(tree->num_levels==3 && (tree->node_capacity[0]==8) && (tree->node_capacity[1]==4) && (tree->node_capacity[2]==8)) { __m128i lvl_0_a = _mm_load_si128(&(tree->key_array[0][0])); __m128i lvl_0_b = _mm_load_si128(&(tree->key_array[0][0])+4); for (size_t i = 0; i < num_probes/4; ++i) { __m128i k=_mm_load_si128((__m128i*)&probe[4*i]); probe_hardcoded(tree,k,result2,lvl_0_a, lvl_0_b, 4*i); } flag=1; //Setting flag to determine whether result2 needs to be published or not } gettimeofday(&stop_3, NULL); int ch=0; printf("Enter 1 if you want to print the results along with the time:"); scanf("%d",&ch); if(ch==1){ for (size_t i = 0; i < num_probes; ++i) { if(flag==1) fprintf(stdout, "%d:%d %u %u %u\n", i,probe[i], result[i], result1[i], result2[i]); else fprintf(stdout, "%d:%d %u %u\n", i,probe[i], result[i], result1[i]); } } printf("Method 1 took %lu.\n", stop_1.tv_usec - start_1.tv_usec); printf("Method 2 took %lu.\n", stop_2.tv_usec - start_2.tv_usec); if(flag==1)printf("Method 3 took %lu.\n", stop_3.tv_usec - start_3.tv_usec); free(result); free(result1); free(result2); free(probe); cleanup_index(tree); return EXIT_SUCCESS; }