Untitled
user_4058768
plain_text
a year ago
3.9 kB
7
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