commit 58c74ce37d839977877f35b4bb41ac09a83e7c14
parent 3f0ec8be0e6084e8b865ac99cd077e0a7479b72b
Author: NunoSempere <nuno.sempere@protonmail.com>
Date: Fri, 2 Jun 2023 12:44:36 -0600
feat: rand not thread safe, use rand_r throughout
Diffstat:
2 files changed, 34 insertions(+), 37 deletions(-)
diff --git a/C-optimized/out/samples b/C-optimized/out/samples
Binary files differ.
diff --git a/C-optimized/samples.c b/C-optimized/samples.c
@@ -6,7 +6,7 @@
const float PI = 3.14159265358979323846;
-#define N 1000000
+#define N 100000000
//Array helpers
@@ -47,54 +47,42 @@ void array_cumsum(float* array_to_sum, float* array_cumsummed, int length)
}
}
-float rand_float(float to)
+float rand_float(float to, unsigned int* seed)
{
- return ((float)rand() / (float)RAND_MAX) * to;
+ return ((float)rand_r(seed) / (float)RAND_MAX) * to;
}
-float ur_normal()
+float ur_normal(unsigned int* seed)
{
- float u1 = rand_float(1.0);
- float u2 = rand_float(1.0);
+ float u1 = rand_float(1.0, seed);
+ float u2 = rand_float(1.0, seed);
float z = sqrtf(-2.0 * log(u1)) * sin(2 * PI * u2);
return z;
}
-inline float random_uniform(float from, float to)
+inline float random_uniform(float from, float to, unsigned int* seed)
{
- return ((float)rand() / (float)RAND_MAX) * (to - from) + from;
+ return ((float) rand_r(seed) / (float)RAND_MAX) * (to - from) + from;
}
-inline float random_normal(float mean, float sigma)
+inline float random_normal(float mean, float sigma, unsigned int* seed)
{
- return (mean + sigma * ur_normal());
+ return (mean + sigma * ur_normal(seed));
}
-inline float random_lognormal(float logmean, float logsigma)
+inline float random_lognormal(float logmean, float logsigma, unsigned int* seed)
{
- return expf(random_normal(logmean, logsigma));
+ return expf(random_normal(logmean, logsigma, seed));
}
-inline float random_to(float low, float high)
+inline float random_to(float low, float high, unsigned int* seed)
{
const float NORMAL95CONFIDENCE = 1.6448536269514722;
float loglow = logf(low);
float loghigh = logf(high);
float logmean = (loglow + loghigh) / 2;
float logsigma = (loghigh - loglow) / (2.0 * NORMAL95CONFIDENCE);
- return random_lognormal(logmean, logsigma);
-}
-
-void array_random_to(float* array, int length, float low, float high)
-{
- int i;
- #pragma omp private(i)
- {
- #pragma omp for
- for (i = 0; i < length; i++) {
- array[i] = random_to(low, high);
- }
- }
+ return random_lognormal(logmean, logsigma, seed);
}
int split_array_get_my_length(int index, int total_length, int n_threads)
@@ -103,6 +91,7 @@ int split_array_get_my_length(int index, int total_length, int 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);
@@ -145,8 +134,8 @@ void mixture(float* dists[], float* weights, int n_dists, float* results)
free(normalized_weights);
free(cummulative_weights);
}
-
-void mixture_f(float (*samplers[])(void), float* weights, int n_dists, float** results, int n_threads)
+*/
+void mixture_f(float (*samplers[])(unsigned int* ), float* weights, int n_dists, float** results, int n_threads)
{
float sum_weights = array_sum(weights, n_dists);
float* normalized_weights = malloc(n_dists * sizeof(float));
@@ -160,6 +149,11 @@ void mixture_f(float (*samplers[])(void), float* weights, int n_dists, float** r
//create var holders
float p1;
int sample_index, i, own_length;
+ unsigned int* seeds[n_threads];
+ for(unsigned int i=0; i<n_threads; i++){
+ seeds[i] = malloc(sizeof(unsigned int));
+ *seeds[i] = i;
+ }
#pragma omp parallel private(i, p1, sample_index, own_length)
{
@@ -167,10 +161,10 @@ void mixture_f(float (*samplers[])(void), float* weights, int n_dists, float** r
for (i = 0; i < n_threads; i++) {
own_length = split_array_get_my_length(i, N, n_threads);
for (int j = 0; j < own_length; j++) {
- p1 = random_uniform(0, 1);
+ p1 = random_uniform(0, 1, seeds[i]);
for (int k = 0; k < n_dists; k++) {
if (p1 < cummulative_weights[k]) {
- results[i][j] = samplers[k]();
+ results[i][j] = samplers[k](seeds[i]);
break;
}
}
@@ -179,26 +173,29 @@ void mixture_f(float (*samplers[])(void), float* weights, int n_dists, float** r
}
free(normalized_weights);
free(cummulative_weights);
+ for(unsigned int i=0; i<n_threads; i++){
+ free(seeds[i]);
+ }
}
-float sample_0()
+float sample_0(unsigned int* seed)
{
return 0;
}
-float sample_1()
+float sample_1(unsigned int* seed)
{
return 1;
}
-float sample_few()
+float sample_few(unsigned int* seed)
{
- return random_to(1, 3);
+ return random_to(1, 3, seed);
}
-float sample_many()
+float sample_many(unsigned int* seed)
{
- return random_to(2, 10);
+ return random_to(2, 10, seed);
}
void split_array_allocate(float** meta_array, int length, int divide_into)
@@ -265,7 +262,7 @@ int main()
// Generate mixture
int n_dists = 4;
float weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 };
- float (*samplers[])(void) = { sample_0, sample_1, sample_few, sample_many };
+ float (*samplers[])(unsigned int* ) = { sample_0, sample_1, sample_few, sample_many };
mixture_f(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);