Advertisement
Guest User

Untitled

a guest
Mar 1st, 2016
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.14 KB | None | 0 0
  1. /*
  2. compile:
  3. gcc minimal_parallel_compute_distances.c -Wall -g -fopenmp -o minimal
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <sys/time.h>
  9. #include <omp.h>
  10.  
  11. #define DMAX 10000000
  12.  
  13.  
  14. // -- kmeans --
  15. int n               = 0;        // number of points
  16. int d               = 0;        // number of dimensions
  17. int k               = 0;        // number of clusters
  18. int p               = 0;        // number of threads
  19. double **dataset    = NULL;     // matrix of points
  20.  
  21. // -- time and throughput --
  22. int iters               = 0;
  23. long int total_ops      = 0;
  24. long int total_iters    = 0;
  25. double time_spent       = 0;
  26. double throughput       = 0;
  27. double mean_time_spent  = 0;
  28. double mean_throughput  = 0;
  29. double mean_total_iters = 0;
  30.  
  31. // -- init_centroids --
  32. double **centroids          = NULL;     // (k, d) matrix
  33. int *clusters               = NULL;     // (n, ) vector
  34. double *distances           = NULL;     // (n, ) vector
  35. double *dist_sum_threads    = NULL;     // (p, ) vector
  36. long int *total_ops_threads = NULL;     // (p, ) vector
  37. int chunk                   = 0;
  38. double dist_sum             = 0;
  39. double wtime_start          = 0;        // start time using omp_get_wtime()
  40. double wtime_end            = 0;        // end time   using omp_get_wtime()
  41. double wtime_spent          = 0;        // wtime_end - wtime_start
  42. double mean_wtime_spent     = 0;
  43.  
  44.  
  45. double **parallel_compute_distances (double **dataset, int n, int d, int k, long int *total_ops) {
  46.    
  47.     double dist=0, error=0, mindist=0;
  48.    
  49.     int cn, cd, ck, mink, id, cp;
  50.                
  51.     // reset before parallel region
  52.     dist_sum = 0;            
  53.    
  54.     // -- start time --
  55.     wtime_start = omp_get_wtime ();
  56.    
  57.     // parallel loop
  58.     # pragma omp parallel shared(distances, clusters, centroids, dataset, chunk, dist_sum, dist_sum_threads) private(id, cn, ck, cd, cp, error, dist, mindist, mink)
  59.     {
  60.         id = omp_get_thread_num();
  61.         dist_sum_threads[id] = 0;               // reset
  62.  
  63.         // 2. recompute distances against centroids
  64.         # pragma omp for schedule(static,chunk)
  65.         for (cn=0; cn<n; cn++) {
  66.            
  67.             mindist = DMAX;
  68.             mink = 0;
  69.            
  70.             for (ck=0; ck<k; ck++) {
  71.                
  72.                 dist = 0;
  73.                
  74.                 for (cd=0; cd<d; cd++) {
  75.                    
  76.                     error = dataset[cn][cd] - centroids[ck][cd];
  77.                     dist = dist + (error * error);                               total_ops_threads[id]++;
  78.                 }
  79.                
  80.                 if (dist < mindist) {
  81.                     mindist = dist;
  82.                     mink = ck;
  83.                 }
  84.             }
  85.            
  86.             distances[cn]           = mindist;
  87.             clusters[cn]            = mink;
  88.             dist_sum_threads[id]    += mindist;
  89.         }
  90.        
  91.        
  92.         // bad parallel reduction
  93.         //#pragma omp parallel for reduction(+:dist_sum)
  94.         //for (cp=0; cp<p; cp++){            
  95.         //    dist_sum += dist_sum_threads[cp];
  96.         //}
  97.        
  98.     }
  99.    
  100.    
  101.     // -- end time --
  102.     wtime_end = omp_get_wtime ();
  103.    
  104.     // -- total wall time --
  105.     wtime_spent = wtime_end - wtime_start;
  106.    
  107.     // sequential reduction
  108.     for (cp=0; cp<p; cp++)      
  109.         dist_sum += dist_sum_threads[cp];
  110.        
  111.    
  112.     // stats
  113.     *(total_ops) = 0;
  114.     for (cp=0; cp<p; cp++)
  115.         *(total_ops) += total_ops_threads[cp];
  116.            
  117.     return centroids;
  118. }
  119.  
  120. void free_matrix(void **matrix, int n) {
  121.    
  122.     if (!matrix) {
  123.         printf("No matrix to release");
  124.         return;
  125.     }
  126.    
  127.     int i = 0;
  128.    
  129.     for (i=0; i<n; i++) {
  130.         free(matrix[i]);
  131.     }
  132.    
  133.     free(matrix);    
  134. }
  135.  
  136. void print_matrix(double **matrix, int n, int m) {
  137.    
  138.     int i = 0, j = 0;
  139.    
  140.     if (!matrix) {
  141.         printf("No matrix to display");
  142.         return;
  143.     }
  144.    
  145.     for (i=0; i<n; i++) {
  146.        
  147.         for (j=0; j<m; j++) {
  148.             printf("%.2f ", matrix[i][j]);
  149.         }
  150.         printf("\n");
  151.     }
  152. }
  153.  
  154.  
  155. void load_data () {
  156.    
  157.     int cn = 0, cd = 0, ck = 0;
  158.    
  159.     // init dataset
  160.     dataset = (double**) malloc( sizeof(double*) * n);
  161.    
  162.     if (!dataset) {
  163.         printf("Error on memory allocation");
  164.         exit(1);
  165.     }
  166.    
  167.     for (cn=0; cn<n; cn++) {
  168.        
  169.         dataset[cn] = (double *) malloc( sizeof(double) * d);
  170.        
  171.         if (!dataset[cn]) {
  172.             printf("Error on memory allocation");
  173.             exit(1);
  174.         }
  175.        
  176.         for (cd=0; cd<d; cd++)
  177.             dataset[cn][cd] = cn*cd+cn+cd;    // some arbitrary number
  178.        
  179.     }
  180.        
  181.     printf ("dataset loaded\n");
  182.    
  183.     // init centroids
  184.     centroids = (double**) malloc( sizeof(double*) * n);
  185.    
  186.     if (!centroids) {
  187.         printf("Error on memory allocation");
  188.         exit(1);
  189.     }
  190.    
  191.     for (ck=0; ck<k; ck++) {
  192.        
  193.         centroids[ck] = (double *) malloc( sizeof(double) * d);
  194.        
  195.         if (!centroids[ck]) {
  196.             printf("Error on memory allocation");
  197.             exit(1);
  198.         }
  199.        
  200.         for (cd=0; cd<d; cd++)
  201.             centroids[ck][cd] = ck+1;    // [1,..,1], [2,..,2], ..., [16,..,16]
  202.        
  203.     }
  204.        
  205.     printf ("centroids loaded\n");
  206.    
  207.     //print_matrix (dataset, n, d);
  208.     //print_matrix (centroids, k, d);
  209.    
  210. }
  211.  
  212. void run_parallel_compute_distances (double **dataset, int n, int d, int k, double *time_spent, double *throughput, long int *total_ops) {
  213.    
  214.     // init memory
  215.     clusters            = (int*) malloc (sizeof(int) * n);
  216.     distances           = (double*) malloc (sizeof(double) * n);
  217.     dist_sum_threads    = (double*) malloc (sizeof(double) * p);
  218.  
  219.  
  220.     // init total ops by thread
  221.     total_ops_threads   = (long int *) malloc(sizeof(long int) * p);
  222.     int cp;
  223.     for (cp=0; cp<p; cp++)
  224.         total_ops_threads[cp] = 0;
  225.    
  226.    
  227.     // run main function
  228.     parallel_compute_distances (dataset, n, d, k, total_ops);
  229.  
  230.  
  231.     // stats
  232.     *throughput = (*total_ops/1000000.0);           // millions of opers
  233.     *throughput = (*throughput / wtime_spent);      // millions of opers / time (seconds)
  234.    
  235.     // free memory
  236.     free (distances);
  237.     free (clusters);
  238.     free (dist_sum_threads);
  239.     free (total_ops_threads);
  240.    
  241. }
  242.  
  243. int main (int argc, char *argv[]) {
  244.    
  245.     // problem size
  246.     n = 100000;     // number of points
  247.     d = 40;         // number of dimensions
  248.     k = 16;         // number of clusters
  249.    
  250.     // load dataset
  251.     load_data ();
  252.    
  253.     // define p and chunk
  254.     int id;
  255.     #pragma omp parallel shared(p, chunk)
  256.     {
  257.         id = omp_get_thread_num();
  258.        
  259.         // set p and chunk
  260.         if (id == 0) {
  261.             p = omp_get_num_threads();
  262.             chunk = n/p;
  263.         }  
  264.     }
  265.    
  266.     // run it
  267.     int i;
  268.     iters = 5;
  269.     for (i=0; i<iters; i++) {    
  270.        
  271.         // reset vars
  272.         wtime_spent = 0;
  273.         throughput  = 0;
  274.         total_ops   = 0;
  275.         total_iters = 0;
  276.        
  277.         run_parallel_compute_distances (dataset, n, d, k, &time_spent, &throughput, &total_ops);
  278.        
  279.         printf ("test: %d, wall time: %.8f, ops: %ld, throughput (millions of opers/sec): %.8f, dist_sum: %.4f\n", i+1, wtime_spent, total_ops, throughput, dist_sum);
  280.        
  281.         mean_time_spent  += time_spent;
  282.         mean_wtime_spent += wtime_spent;
  283.         mean_throughput  += throughput;
  284.         mean_total_iters += total_iters;
  285.     }
  286.    
  287.     mean_time_spent  /= iters;
  288.     mean_wtime_spent /= iters;
  289.     mean_throughput  /= iters;
  290.     mean_total_iters /= iters;
  291.    
  292.     printf ("size n: %d\n", n);
  293.     printf ("threads p: %d\n", p);
  294.     printf ("compute distances mean time spent: %.8f\n", mean_time_spent);
  295.     printf ("compute distances mean wall time spent: %.8f\n", mean_wtime_spent);
  296.     printf ("compute distances mean throughput: %.8f\n", mean_throughput);
  297.    
  298.    
  299.     // free'em
  300.     free_matrix ((void **) dataset, n);
  301.     free_matrix ((void **) centroids, k);
  302.    
  303.     return 0;    
  304. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement