Untitled

 avatar
user_4058768
plain_text
13 days ago
3.9 kB
3
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <math.h>

// Structure to pass arguments to threads
typedef struct {
	long long points_per_thread;
	long long points_in_circle;
	unsigned int seed;
} ThreadData;

// Thread function to generate random points and count those in the circle
void* monte_carlo_task(void* arg) {
	ThreadData* data = (ThreadData*)arg;
	long long local_count = 0;
	double x, y;
    
	// Each thread uses a different seed to avoid correlation
	unsigned int local_seed = data->seed;
    
	for (long long i = 0; i < data->points_per_thread; i++) {
    	// Generate random points between -1 and 1
    	x = (double)rand_r(&local_seed) / RAND_MAX * 2 - 1;
    	y = (double)rand_r(&local_seed) / RAND_MAX * 2 - 1;
   	 
    	// Check if point is inside circle
    	if (x*x + y*y <= 1)
        	local_count++;
	}
    
	// Store result in the structure
	data->points_in_circle = local_count;
    
	return NULL;
}

int main(int argc, char* argv[]) {
	long long total_points = 100000000; // 100 million points by default
	int num_threads = 4; // Default number of threads
	double pi_estimate, pi_error;
	double execution_time;
	long long total_in_circle = 0;
    
	// Check if number of threads is provided as command line argument
	if (argc > 1) {
    	num_threads = atoi(argv[1]);
    	if (num_threads <= 0) {
        	printf("Number of threads must be positive, using default (4)\n");
        	num_threads = 4;
    	}
	}
    
	// Optional: Allow specifying number of points via command line
	if (argc > 2) {
    	total_points = atoll(argv[2]);
    	if (total_points <= 0) {
        	printf("Number of points must be positive, using default (100M)\n");
        	total_points = 100000000;
    	}
	}
    
	printf("Running Monte Carlo Pi estimation with %d threads and %lld points\n",
       	num_threads, total_points);
    
	// Allocate thread and data arrays
	pthread_t* threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t));
	ThreadData* thread_data = (ThreadData*)malloc(num_threads * sizeof(ThreadData));
    
	if (!threads || !thread_data) {
    	perror("Failed to allocate memory");
    	return 1;
	}
    
	// Calculate points per thread (handle remainder)
	long long points_per_thread = total_points / num_threads;
	long long remainder = total_points % num_threads;
    
	// Start timing
	struct timespec start_time, end_time;
	clock_gettime(CLOCK_MONOTONIC, &start_time);
    
	// Create threads
	for (int i = 0; i < num_threads; i++) {
    	thread_data[i].points_per_thread = points_per_thread + (i < remainder ? 1 : 0);
    	thread_data[i].points_in_circle = 0;
    	thread_data[i].seed = time(NULL) + i; // Different seed for each thread
   	 
    	if (pthread_create(&threads[i], NULL, monte_carlo_task, &thread_data[i]) != 0) {
        	perror("Failed to create thread");
        	return 1;
    	}
	}
    
	// Wait for all threads to complete
	for (int i = 0; i < num_threads; i++) {
    	if (pthread_join(threads[i], NULL) != 0) {
        	perror("Failed to join thread");
        	return 1;
    	}
    	total_in_circle += thread_data[i].points_in_circle;
	}
    
	// Stop timing
	clock_gettime(CLOCK_MONOTONIC, &end_time);
    
	// Calculate pi and execution time
	pi_estimate = 4.0 * total_in_circle / total_points;
	execution_time = (end_time.tv_sec - start_time.tv_sec) +
                	(end_time.tv_nsec - start_time.tv_nsec) / 1e9;
	pi_error = fabs((pi_estimate - M_PI) / M_PI * 100);
    
	// Print results
	printf("Estimated Pi: %.10f\n", pi_estimate);
	printf("Actual Pi:	%.10f\n", M_PI);
	printf("Error:    	%.10f%%\n", pi_error);
	printf("Execution time: %.6f seconds\n", execution_time);
    
	// Free allocated memory
	free(threads);
	free(thread_data);
    
	return 0;
}





Editor is loading...
Leave a Comment