time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

commit cdec5b6fce4cef8daf7d1de3f76493266d7c8693
parent ff3685766b18c89ffb753de753e16ed38693c31b
Author: NunoSempere <nuno.sempere@protonmail.com>
Date:   Fri,  2 Jun 2023 16:05:42 -0600

remove old code from samples.c

Diffstat:
MC/samples.c | 171++++++++++++++++++++++++++-----------------------------------------------------
1 file changed, 56 insertions(+), 115 deletions(-)

diff --git a/C/samples.c b/C/samples.c @@ -18,18 +18,6 @@ void array_print(float* array, int length) printf("\n"); } -void array_fill(float* array, int length, float item) -{ - int i; - #pragma omp private(i) - { - #pragma omp for - for (i = 0; i < length; i++) { - array[i] = item; - } - } -} - float array_sum(float* array, int length) { float output = 0.0; @@ -47,10 +35,57 @@ void array_cumsum(float* array_to_sum, float* array_cumsummed, int length) } } +// Split array helpers +int split_array_get_my_length(int index, int total_length, int n_threads) +{ + return (total_length % n_threads > index ? total_length / n_threads + 1 : total_length / n_threads); +} + +void split_array_allocate(float** meta_array, int length, int divide_into) +{ + int own_length; + + for (int i = 0; i < divide_into; i++) { + own_length = split_array_get_my_length(i, length, divide_into); + meta_array[i] = malloc(own_length * sizeof(float)); + } +} + +void split_array_free(float** meta_array, int divided_into) +{ + for (int i = 0; i < divided_into; i++) { + free(meta_array[i]); + } + free(meta_array); +} + +float split_array_sum(float** meta_array, int length, int divided_into) +{ + int i; + float output; + float* partial_sum = malloc(divided_into * sizeof(float)); + + #pragma omp private(i) shared(partial_sum) + for (int i = 0; i < divided_into; i++) { + float own_partial_sum = 0; + int own_length = split_array_get_my_length(i, length, divided_into); + for (int j = 0; j < own_length; j++) { + own_partial_sum += meta_array[i][j]; + } + partial_sum[i] = own_partial_sum; + } + for (int i = 0; i < divided_into; i++) { + output += partial_sum[i]; + } + return output; +} + +// Distribution & sampling functions + float rand_float(float to, unsigned int* seed) { return ((float)rand_r(seed) / (float)RAND_MAX) * to; - // See: <https://stackoverflow.com/questions/43151361/how-to-create-thread-safe-random-number-generator-in-c-using-rand-r> + // See: <https://stackoverflow.com/questions/43151361/how-to-create-thread-safe-random-number-generator-in-c-using-rand-r> for why to use rand_r: // rand() is not thread-safe, as it relies on (shared) hidden state. } @@ -87,58 +122,11 @@ inline float random_to(float low, float high, unsigned int* seed) return random_lognormal(logmean, logsigma, seed); } -int split_array_get_my_length(int index, int total_length, int n_threads) -{ - return (total_length % n_threads > index ? total_length / n_threads + 1 : total_length / n_threads); -} - -//Old version, don't use it!! Optimized version is called mixture_f. This one is just for display -/* -void mixture(float* dists[], float* weights, int n_dists, float* results) -{ - float sum_weights = array_sum(weights, n_dists); - float* normalized_weights = malloc(n_dists * sizeof(float)); - for (int i = 0; i < n_dists; i++) { - normalized_weights[i] = weights[i] / sum_weights; - } - - float* cummulative_weights = malloc(n_dists * sizeof(float)); - array_cumsum(normalized_weights, cummulative_weights, n_dists); - - //create var holders - float p1, p2; - int index_found, index_counter, sample_index, i; - - #pragma omp parallel private(i, p1, p2, index_found, index_counter, sample_index) - { - #pragma omp for - for (i = 0; i < N; i++) { - p1 = random_uniform(0, 1); - p2 = random_uniform(0, 1); - - index_found = 0; - index_counter = 0; - - while ((index_found == 0) && (index_counter < n_dists)) { - if (p1 < cummulative_weights[index_counter]) { - index_found = 1; - } else { - index_counter++; - } - } - if (index_found != 0) { - sample_index = (int)(p2 * N); - results[i] = dists[index_counter][sample_index]; - } else - printf("This shouldn't be able to happen.\n"); - } - } - free(normalized_weights); - free(cummulative_weights); -} -*/ -void mixture_f(float (*samplers[])(unsigned int* ), float* weights, int n_dists, float** results, int n_threads) +// Mixture function +void mixture(float (*samplers[])(unsigned int* ), float* weights, int n_dists, float** results, int n_threads) { + // You can see a simpler version of this function in the git history + // or in C-02-better-algorithm-one-thread/ float sum_weights = array_sum(weights, n_dists); float* normalized_weights = malloc(n_dists * sizeof(float)); for (int i = 0; i < n_dists; i++) { @@ -180,6 +168,9 @@ void mixture_f(float (*samplers[])(unsigned int* ), float* weights, int n_dists, } } +// Functions used for the BOTEC. +// Their type has to be the same, as we will be passing them around. + float sample_0(unsigned int* seed) { return 0; @@ -200,53 +191,9 @@ float sample_many(unsigned int* seed) return random_to(2, 10, seed); } -void split_array_allocate(float** meta_array, int length, int divide_into) -{ - int own_length; - - for (int i = 0; i < divide_into; i++) { - own_length = split_array_get_my_length(i, length, divide_into); - meta_array[i] = malloc(own_length * sizeof(float)); - } -} - -void split_array_free(float** meta_array, int divided_into) -{ - for (int i = 0; i < divided_into; i++) { - free(meta_array[i]); - } - free(meta_array); -} - -float split_array_sum(float** meta_array, int length, int divided_into) -{ - int i; - float output; - float* partial_sum = malloc(divided_into * sizeof(float)); - - #pragma omp private(i) shared(partial_sum) - for (int i = 0; i < divided_into; i++) { - float own_partial_sum = 0; - int own_length = split_array_get_my_length(i, length, divided_into); - for (int j = 0; j < own_length; j++) { - own_partial_sum += meta_array[i][j]; - } - partial_sum[i] = own_partial_sum; - } - for (int i = 0; i < divided_into; i++) { - output += partial_sum[i]; - } - return output; -} - int main() { - //initialize randomness - srand(time(NULL)); - // clock_t start, end; - // start = clock(); - // Toy example // Declare variables in play float p_a, p_b, p_c; @@ -266,16 +213,10 @@ int main() float weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; float (*samplers[])(unsigned int* ) = { sample_0, sample_1, sample_few, sample_many }; - mixture_f(samplers, weights, n_dists, dist_mixture, n_threads); + mixture(samplers, weights, n_dists, dist_mixture, n_threads); printf("Sum(dist_mixture, N)/N = %f\n", split_array_sum(dist_mixture, N, n_threads) / N); // array_print(dist_mixture[0], N); split_array_free(dist_mixture, n_threads); - // end = clock(); - // printf("Time (ms): %f\n", ((double)(end - start)) / (CLOCKS_PER_SEC) * 1000); - // ^ Will only measure how long it takes the inner main to run, not the whole program, - // including e.g., loading the program into memory or smth. - // Also CLOCKS_PER_SEC in POSIX is a constant equal to 1000000. - // See: https://stackoverflow.com/questions/10455905/why-is-clocks-per-sec-not-the-actual-number-of-clocks-per-second return 0; }