Advertisement
nux95

MC Pi - Threaded

May 26th, 2013
381
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.29 KB | None | 0 0
  1. /**
  2.  * coding: utf-8
  3.  *
  4.  * Copyright (C) 2013, Niklas Rosenstein
  5.  * All rights reserved.
  6.  *
  7.  * Licensed under the GNU General Public License.
  8.  */
  9.  
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include <time.h>
  15. #include <pthread.h>
  16.  
  17. #define TRUE (1)
  18. #define FALSE (0)
  19.  
  20. enum EXITCODE {
  21.     EXITCODE_OK = 0,
  22.     EXITCODE_INVALIDARGUMENTS,
  23.     EXITCODE_UNKOWNARGUMENTS,
  24.     EXITCODE_FAILURE,
  25.     EXITCODE_MEMORY,
  26. };
  27.  
  28. enum ARGTYPE {
  29.     ARGTYPE_INT,
  30.     ARGTYPE_BOOL,
  31.     ARGTYPE_STRING,
  32.     ARGTYPE_GIVEN,
  33. };
  34.  
  35. enum PARSERESULT {
  36.     PARSERESULT_OK = 0,
  37.     PARSERESULT_NOTOK,
  38.     PARSERESULT_MISSINGARGUMENT,
  39.     PARSERESULT_WRONGARGUMENT,
  40.     PARSERESULT_WRONGARGTYPE,
  41.     PARSERESULT_NOTSUPPORTED,
  42. };
  43.  
  44. typedef enum ARGTYPE ARGTYPE;
  45. typedef enum PARSERESULT PARSERESULT;
  46.  
  47.  
  48. int str_is_int(char* string) {
  49.     if (*string == '+' || *string == '-') string++;
  50.     while (*string != 0) {
  51.         if (*string < '0' || *string > '9') return FALSE;
  52.         string++;
  53.     }
  54.     return TRUE;
  55. }
  56.  
  57. char* g_matched = NULL;
  58.  
  59. PARSERESULT check_arg(int argc, char** argv, int* i, char* argname,
  60.                       void* dest, ARGTYPE type) {
  61.     if (strcmp(argv[*i], argname) == 0) {
  62.         if (*i + 1 >= argc && type != ARGTYPE_GIVEN) {
  63.             printf("Missing value for argument %s\n", argname);
  64.             exit(EXIT_FAILURE);
  65.             return PARSERESULT_MISSINGARGUMENT;
  66.         }
  67.     }
  68.     else {
  69.         return PARSERESULT_NOTOK;
  70.     }
  71.     if (g_matched) g_matched[*i] = TRUE;
  72.     if (!dest) return PARSERESULT_OK;
  73.  
  74.     int increment = TRUE;
  75.     char* value = argv[*i + 1];
  76.     PARSERESULT result = PARSERESULT_OK;
  77.     switch (type) {
  78.         case ARGTYPE_INT:
  79.             if (!str_is_int(value)) {
  80.                 printf("Integer value expected for argument %s.\n", argname);
  81.                 return PARSERESULT_WRONGARGUMENT;
  82.             }
  83.             *(int*) dest = atoi(value);
  84.             break;
  85.         case ARGTYPE_BOOL:
  86.             result = PARSERESULT_NOTSUPPORTED;
  87.             break;
  88.         case ARGTYPE_STRING:
  89.             result = PARSERESULT_NOTSUPPORTED;
  90.             break;
  91.         case ARGTYPE_GIVEN:
  92.             increment = FALSE;
  93.             *(char*) dest = TRUE;
  94.             break;
  95.         default:
  96.             return PARSERESULT_WRONGARGTYPE;
  97.     }
  98.  
  99.     if (increment) (*i)++;
  100.     if (g_matched) g_matched[*i] = TRUE;
  101.     return result;
  102. }
  103.  
  104. int alloc_failed() {
  105.     printf("Memory error, allocation failed.\n");
  106.     return EXITCODE_MEMORY;
  107. }
  108.  
  109.  
  110. double rand_01() {
  111.     return (double) rand() / (double) RAND_MAX;
  112. }
  113.  
  114. double pi_mc(int iterations) {
  115.     long long inner = 0;
  116.     long long outer = 0;
  117.     int i;
  118.     for (i=0; i < iterations; i++) {
  119.         double x = rand_01();
  120.         double y = rand_01();
  121.         double d = sqrt(pow(x, 2.0) + pow(y, 2.0));
  122.         if (d <= 1.0) {
  123.             inner++;
  124.         }
  125.         else {
  126.             outer++;
  127.         }
  128.     }
  129.  
  130.     return ((double) inner / (double) iterations) * 4;
  131. }
  132.  
  133.  
  134. struct PIThreadData {
  135.     int iterations;
  136.     double out;
  137. };
  138.  
  139. void* pi_mc_threaded(void* ptr) {
  140.     struct PIThreadData* data = ptr;
  141.     data->out = pi_mc(data->iterations);
  142. }
  143.  
  144.  
  145. int main(int argc, char** argv) {
  146.     int i;
  147.  
  148.     // Arguments structure.
  149.     struct {
  150.         char stats;
  151.         char colored;
  152.         int iterations;
  153.         int threads;
  154.     } args = {0};
  155.     args.iterations = (int) pow(10, 6);
  156.     args.threads = 1;
  157.  
  158.     // Parse command-line arguments.
  159.     int pos_arg = 0;
  160.     g_matched = calloc(argc, 1);
  161.     if (!g_matched) {
  162.         return alloc_failed();
  163.     }
  164.  
  165.     for (i=1; i < argc; i++) {
  166.         check_arg(argc, argv, &i, "-iterations", &args.iterations, ARGTYPE_INT);
  167.         check_arg(argc, argv, &i, "-threads", &args.threads, ARGTYPE_INT);
  168.         check_arg(argc, argv, &i, "-stats", &args.stats, ARGTYPE_GIVEN);
  169.         check_arg(argc, argv, &i, "-colored", &args.colored, ARGTYPE_GIVEN);
  170.     }
  171.  
  172.     // Print out not-matched arguments.
  173.     for (i=1; i < argc; i++) {
  174.         if (g_matched[i] == 0) {
  175.             printf("Unkown argument %d: %s\n", i, argv[i]);
  176.             return EXITCODE_UNKOWNARGUMENTS;
  177.         }
  178.     }
  179.  
  180.     free(g_matched);
  181.     g_matched = NULL;
  182.  
  183.     // Validate arguments.
  184.     if (args.iterations < 1) {
  185.         printf("Argument -iterations must be an integer greater than zero.\n");
  186.         return EXITCODE_INVALIDARGUMENTS;
  187.     }
  188.     if (args.threads < 1) {
  189.         printf("Argument -threads must be an integer greater than zero.\n");
  190.         return EXITCODE_INVALIDARGUMENTS;
  191.     }
  192.  
  193.     // Begin computation.
  194.     clock_t t_start, t_delta;
  195.     double pi = 0;
  196.  
  197.     if (args.threads == 1) {
  198.         t_start = clock();
  199.         pi = pi_mc(args.iterations);
  200.         t_delta = clock() - t_start;
  201.     }
  202.     else {
  203.         pthread_t* threads = malloc(sizeof(pthread_t) * args.threads);
  204.         if (!threads) {
  205.             return alloc_failed();
  206.         }
  207.  
  208.         struct PIThreadData* values = malloc(sizeof(struct PIThreadData) * args.threads);
  209.         if (!values) {
  210.             free(threads);
  211.             return alloc_failed();
  212.         }
  213.  
  214.         t_start = clock();
  215.         for (i=0; i < args.threads; i++) {
  216.             values[i].iterations = args.iterations;
  217.             values[i].out = 0.0;
  218.             pthread_create(threads + i, NULL, pi_mc_threaded, values + i);
  219.         }
  220.         for (i=0; i < args.threads; i++) {
  221.             pthread_join(threads[i], NULL);
  222.             pi += values[i].out;
  223.         }
  224.         t_delta = clock() - t_start;
  225.  
  226.         free(threads);
  227.         threads = NULL;
  228.         free(values);
  229.         values = NULL;
  230.  
  231.         pi /= (double) args.threads;
  232.     }
  233.  
  234.     if (args.colored) {
  235.         printf("\033[33m%f\033[0m\n", pi);
  236.     }
  237.     else {
  238.         printf("%f\n", pi);
  239.     }
  240.  
  241.     // Show stats if desired.
  242.     if (args.stats) {
  243.         printf("\n");
  244.         printf("Number of iterations:  %d\n", args.iterations * args.threads);
  245.         printf("Method:                Monte Carlo\n");
  246.         printf("Evaluation time:       %f sec\n", ((double) t_delta) / CLOCKS_PER_SEC);
  247.         printf("Threads:               ");
  248.         if (args.threads == 1) printf("Main\n");
  249.         else printf("%d\n", args.threads);
  250.     }
  251.  
  252.     return EXITCODE_OK;
  253. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement