Guest User

Untitled

a guest
Feb 24th, 2018
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.78 KB | None | 0 0
  1. /**
  2. * Monte Carlo - Threads exercise
  3. *
  4. * Compile with: gcc ./mcarlo.c -o mcarlo -lpthread -lm
  5. */
  6. #include <unistd.h>
  7. #include <time.h>
  8. #include <math.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <pthread.h>
  12.  
  13. #define RETURN_SUCCESS (0)
  14. #define RETURN_FAILURE (1)
  15. #define THREAD_SUCCESS (RETURN_SUCCESS)
  16. #define THREAD_FAILURE (RETURN_FAILURE)
  17. #define SYSCALL_FAILURE (-1)
  18.  
  19. #define PROGRESS (1)
  20.  
  21. #define WORKER_COUNT (10)
  22. #define WITHIN_CIRCLE(x, y) (sqrt(x*x + y*y) < 1)
  23. #define RANDOM_DOUBLE ((random() / ((double)RAND_MAX + 1)) * 2.0 - 1.0)
  24. #define PI(a, b) ((double)(4.0 * ((double)b / (double)a)))
  25.  
  26. typedef struct s_mcarlo
  27. {
  28. unsigned long long p_todo;
  29. unsigned long long p_count;
  30. unsigned long long p_within_circle;
  31. double pi;
  32. } t_mcarlo;
  33.  
  34. typedef struct s_thread
  35. {
  36. pthread_t thread_id;
  37. pthread_attr_t thread_attr;
  38. unsigned long long points_computed;
  39. int status;
  40. } t_thread;
  41.  
  42. void *worker(void *arg);
  43.  
  44. t_mcarlo mcarlo = {0, 0, 0, 0.0};
  45.  
  46. pthread_mutex_t lock;
  47.  
  48. int main(int argc, char **argv)
  49. {
  50. t_thread threads[WORKER_COUNT];
  51. unsigned int i = 0;
  52. unsigned long long point_number = 0;
  53.  
  54. /* Checking command line parameters */
  55. if (argc < 2)
  56. {
  57. fprintf(stderr, "[^] USAGE: ./mcarlo <point_number>\n");
  58. return RETURN_FAILURE;
  59. }
  60. /* Converting the char* argv[1] into long long */
  61. if ((point_number = atoll(argv[1])) < 1)
  62. {
  63. fprintf(stderr, "[-] point_number should be >= 1\n");
  64. return RETURN_FAILURE;
  65. }
  66. /* Initializing mutex */
  67. if (pthread_mutex_init(&lock, NULL) != 0)
  68. {
  69. printf("[-] Failed to init mutex !\n");
  70. return RETURN_FAILURE;
  71. }
  72. /* Setting the random seed to the currant time in second */
  73. srand(time(NULL));
  74.  
  75. /* Number of points to compute stored in the working structure */
  76. mcarlo.p_todo = point_number;
  77.  
  78. /* Initializing threads, then, start them */
  79. printf("[~] Launching %d threads ..\n", WORKER_COUNT);
  80. for (i = 0 ; i < WORKER_COUNT ; ++i)
  81. {
  82. /* By default, the thread succeed */
  83. threads[i].status = THREAD_SUCCESS;
  84. /* Setting default thread attr */
  85. pthread_attr_init(&threads[i].thread_attr);
  86. /* Starting threads */
  87. if (pthread_create(&threads[i].thread_id, &threads[i].thread_attr, worker, &mcarlo) != RETURN_SUCCESS)
  88. {
  89. fprintf(stderr, "[-] Failed to start thread %d\n", i);
  90. threads[i].status = THREAD_FAILURE; /* Set the thread creation status to know if we have to join() it */
  91. }
  92. }
  93.  
  94. /* Waiting for the threads to finish */
  95. for (i = 0 ; i < WORKER_COUNT ; ++i)
  96. {
  97. unsigned long long *p;
  98. /* Waiting for thread i to finish */
  99. pthread_join(threads[i].thread_id, (void**)&p);
  100. if (p != NULL) /* If worker malloc doesn't failed */
  101. {
  102. threads[i].points_computed = *p;
  103. printf("[~] Thread %d computed %llu points\n", i + 1, threads[i].points_computed);
  104. }
  105. free(p);
  106. }
  107.  
  108. printf("[+] All Threads finished ! %llu/%llu PI = %f\n", mcarlo.p_within_circle, mcarlo.p_count, PI(mcarlo.p_count, mcarlo.p_within_circle));
  109. pthread_mutex_destroy(&lock);
  110. return RETURN_SUCCESS;
  111. }
  112.  
  113. void *worker(void *arg)
  114. {
  115. /* Casting the void* pointer to retrieve our t_mcarlo structure */
  116. t_mcarlo *mcarlo = (t_mcarlo *)arg;
  117. double x = 0, y = 0;
  118. unsigned long long *points_computed;
  119.  
  120. if ((points_computed = malloc(sizeof(unsigned long long) * 1)) == NULL)
  121. return NULL;
  122. while (mcarlo->p_count < mcarlo->p_todo)
  123. {
  124. /* Creating random values (x, y coordinates) */
  125. x = RANDOM_DOUBLE;
  126. y = RANDOM_DOUBLE;
  127.  
  128. /* Locking the mutex, accessing shared memory */
  129. pthread_mutex_lock(&lock);
  130.  
  131. /* Increasing number of computed points */
  132. if (++mcarlo->p_count && WITHIN_CIRCLE(x, y)) /* Check is the coordinates are within the circle */
  133. ++mcarlo->p_within_circle;
  134.  
  135. /* Inc the computed points count to determine how many points a thread has computed */
  136. ++*points_computed;
  137.  
  138. /* Unlocking the mutex, not using shared memory anymore */
  139. pthread_mutex_unlock(&lock);
  140.  
  141. /* Logging some info 10 times if we are in debug/progress mode */
  142. if (PROGRESS && mcarlo->p_count % (mcarlo->p_todo / 10) == 0)
  143. printf("Progress: %llu/%llu -> %f\n", mcarlo->p_within_circle, mcarlo->p_count, PI(mcarlo->p_count, mcarlo->p_within_circle));
  144. }
  145. /* Exiting at the end of the job */
  146. //pthread_exit(points_computed);
  147. return (void *)points_computed;
  148. }
Add Comment
Please, Sign In to add comment