Skip to content

Instantly share code, notes, and snippets.

@SakiiR
Created February 13, 2018 09:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SakiiR/66dab8fb11dde7a62c0aa9d38a6dfdf8 to your computer and use it in GitHub Desktop.
Save SakiiR/66dab8fb11dde7a62c0aa9d38a6dfdf8 to your computer and use it in GitHub Desktop.
Threads / Mutex -> Monte-Carlo
/**
* Monte Carlo - Threads exercise
*
* Compile with: gcc ./mcarlo.c -o mcarlo -lpthread -lm
*/
#include <unistd.h>
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define RETURN_SUCCESS (0)
#define RETURN_FAILURE (1)
#define THREAD_SUCCESS (RETURN_SUCCESS)
#define THREAD_FAILURE (RETURN_FAILURE)
#define SYSCALL_FAILURE (-1)
#define PROGRESS (1)
#define WORKER_COUNT (10)
#define WITHIN_CIRCLE(x, y) (sqrt(x*x + y*y) < 1)
#define RANDOM_DOUBLE ((random() / ((double)RAND_MAX + 1)) * 2.0 - 1.0)
#define PI(a, b) ((double)(4.0 * ((double)b / (double)a)))
typedef struct s_mcarlo
{
unsigned long long p_todo;
unsigned long long p_count;
unsigned long long p_within_circle;
double pi;
} t_mcarlo;
typedef struct s_thread
{
pthread_t thread_id;
pthread_attr_t thread_attr;
unsigned long long points_computed;
int status;
} t_thread;
void *worker(void *arg);
t_mcarlo mcarlo = {0, 0, 0, 0.0};
pthread_mutex_t lock;
int main(int argc, char **argv)
{
t_thread threads[WORKER_COUNT];
unsigned int i = 0;
unsigned long long point_number = 0;
/* Checking command line parameters */
if (argc < 2)
{
fprintf(stderr, "[^] USAGE: ./mcarlo <point_number>\n");
return RETURN_FAILURE;
}
/* Converting the char* argv[1] into long long */
if ((point_number = atoll(argv[1])) < 1)
{
fprintf(stderr, "[-] point_number should be >= 1\n");
return RETURN_FAILURE;
}
/* Initializing mutex */
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("[-] Failed to init mutex !\n");
return RETURN_FAILURE;
}
/* Setting the random seed to the currant time in second */
srand(time(NULL));
/* Number of points to compute stored in the working structure */
mcarlo.p_todo = point_number;
/* Initializing threads, then, start them */
printf("[~] Launching %d threads ..\n", WORKER_COUNT);
for (i = 0 ; i < WORKER_COUNT ; ++i)
{
/* By default, the thread succeed */
threads[i].status = THREAD_SUCCESS;
/* Setting default thread attr */
pthread_attr_init(&threads[i].thread_attr);
/* Starting threads */
if (pthread_create(&threads[i].thread_id, &threads[i].thread_attr, worker, &mcarlo) != RETURN_SUCCESS)
{
fprintf(stderr, "[-] Failed to start thread %d\n", i);
threads[i].status = THREAD_FAILURE; /* Set the thread creation status to know if we have to join() it */
}
}
/* Waiting for the threads to finish */
for (i = 0 ; i < WORKER_COUNT ; ++i)
{
unsigned long long *p;
/* Waiting for thread i to finish */
pthread_join(threads[i].thread_id, (void**)&p);
if (p != NULL) /* If worker malloc doesn't failed */
{
threads[i].points_computed = *p;
printf("[~] Thread %d computed %llu points\n", i + 1, threads[i].points_computed);
}
free(p);
}
printf("[+] All Threads finished ! %llu/%llu PI = %f\n", mcarlo.p_within_circle, mcarlo.p_count, PI(mcarlo.p_count, mcarlo.p_within_circle));
pthread_mutex_destroy(&lock);
return RETURN_SUCCESS;
}
void *worker(void *arg)
{
/* Casting the void* pointer to retrieve our t_mcarlo structure */
t_mcarlo *mcarlo = (t_mcarlo *)arg;
double x = 0, y = 0;
unsigned long long *points_computed;
if ((points_computed = malloc(sizeof(unsigned long long) * 1)) == NULL)
return NULL;
while (mcarlo->p_count < mcarlo->p_todo)
{
/* Creating random values (x, y coordinates) */
x = RANDOM_DOUBLE;
y = RANDOM_DOUBLE;
/* Locking the mutex, accessing shared memory */
pthread_mutex_lock(&lock);
/* Increasing number of computed points */
if (++mcarlo->p_count && WITHIN_CIRCLE(x, y)) /* Check is the coordinates are within the circle */
++mcarlo->p_within_circle;
/* Inc the computed points count to determine how many points a thread has computed */
++*points_computed;
/* Unlocking the mutex, not using shared memory anymore */
pthread_mutex_unlock(&lock);
/* Logging some info 10 times if we are in debug/progress mode */
if (PROGRESS && mcarlo->p_count % (mcarlo->p_todo / 10) == 0)
printf("Progress: %llu/%llu -> %f\n", mcarlo->p_within_circle, mcarlo->p_count, PI(mcarlo->p_count, mcarlo->p_within_circle));
}
/* Exiting at the end of the job */
//pthread_exit(points_computed);
return (void *)points_computed;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment