void *generate_chase(const struct generate_chase_common_args *args, size_t mixer_idx) { char *arena = args->arena; size_t total_memory = args->total_memory; size_t stride = args->stride; size_t tlb_locality = args->tlb_locality; void (*gen_permutation)(perm_t *, size_t, size_t) = args->gen_permutation; const perm_t *mixer = args->mixer + mixer_idx * NR_MIXERS; size_t nr_mixer_indices = args->nr_mixer_indices; size_t nr_tlb_groups = total_memory / tlb_locality; size_t nr_elts_per_tlb = tlb_locality / stride; size_t nr_elts = total_memory / stride; perm_t *tlb_perm; perm_t *perm; size_t i; perm_t *perm_inverse; size_t mixer_scale = stride / nr_mixer_indices; if (verbosity > 1) printf("generating permutation of %zu elements (in %zu TLB groups)\n", nr_elts, nr_tlb_groups); tlb_perm = malloc(nr_tlb_groups * sizeof(*tlb_perm)); gen_permutation(tlb_perm, nr_tlb_groups, 0); perm = malloc(nr_elts * sizeof(*perm)); for (i = 0; i < nr_tlb_groups; ++i) { gen_permutation(&perm[i * nr_elts_per_tlb], nr_elts_per_tlb, tlb_perm[i] * nr_elts_per_tlb); } free(tlb_perm); dassert(is_a_permutation(perm, nr_elts)); if (verbosity > 1) printf("generating inverse permtuation\n"); perm_inverse = malloc(nr_elts * sizeof(*perm)); for (i = 0; i < nr_elts; ++i) { perm_inverse[perm[i]] = i; } dassert(is_a_permutation(perm_inverse, nr_elts)); #define MIXED(x) \ ((x)*stride + mixer[(x) & (NR_MIXERS-1)]*mixer_scale) if (verbosity > 1) printf("threading the chase (mixer_idx = %zu)\n", mixer_idx); for (i = 0; i < nr_elts; ++i) { size_t next; dassert(perm[perm_inverse[i]] == i); assert(*(void **)(arena + MIXED(i)) == NULL); next = perm_inverse[i] + 1; next = (next == nr_elts) ? 0 : next; *(void **)(arena + MIXED(i)) = (void *)(arena + MIXED(perm[next])); } free(perm); free(perm_inverse); return arena + MIXED(0); }
void generate_chase_mixer(struct generate_chase_common_args *args) { size_t nr_mixer_indices = args->nr_mixer_indices; void (*gen_permutation)(perm_t *, size_t, size_t) = args->gen_permutation; perm_t *t = malloc(nr_mixer_indices * sizeof(*t)); if (t == NULL) { fprintf(stderr, "Could not allocate %lu bytes, check stride/memory size?\n", nr_mixer_indices * sizeof(*t)); exit(1); } perm_t *r = malloc(nr_mixer_indices * NR_MIXERS * sizeof(*r)); if (r == NULL) { fprintf(stderr, "Could not allocate %lu bytes, check stride/memory size?\n", nr_mixer_indices * NR_MIXERS * sizeof(*r)); exit(1); } size_t i; size_t j; // we arrange r in a transposed manner so that all of the // data for a particular mixer_idx is packed together. for (i = 0; i < NR_MIXERS; ++i) { gen_permutation(t, nr_mixer_indices, 0); for (j = 0; j < nr_mixer_indices; ++j) { r[j * NR_MIXERS + i] = t[j]; } } free(t); args->mixer = r; }
int main(int argc, char** argv) { int length; if (argc == 2) { int /*res, */ind, *array; sscanf(argv[1], "%d", &length); array = (int *) malloc (sizeof(int)*length); for (ind=0; ind < length; ind ++) { array[ind] = ind+1; } print_arr(array, length); gen_permutation(array, length, length); free(array); array = NULL; } else { printf("Usage: gen_permutations <size of array>\n"); } return 0; }