feat: rand not thread safe, use rand_r throughout
This commit is contained in:
		
							parent
							
								
									3f0ec8be0e
								
							
						
					
					
						commit
						58c74ce37d
					
				
										
											Binary file not shown.
										
									
								
							|  | @ -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); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user