Advertisement
Guest User

Untitled

a guest
Jan 16th, 2017
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.18 KB | None | 0 0
  1. #include <mpi.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5.  
  6. #include "timing.h"
  7.  
  8.  
  9. void print_arr( int* arr, int len ) {
  10.  
  11. unsigned int i;
  12. for( i = 0; i < len; ++i )
  13. printf( "%d ", arr[i] );
  14. printf("\n");
  15. }
  16.  
  17. int is_arr_sorted( int* arr, int len ) {
  18.  
  19. int i;
  20. for( i = 0; i < len - 1; ++i )
  21. if( arr[i] > arr[i+1] )
  22. return 0;
  23. return 1;
  24. }
  25.  
  26. /**
  27. * Determine the index of the beginning of each block
  28. * based on the global splitters
  29. */
  30. void partition( int* data, int len, int* splitters, int num_sp, int* disp) {
  31. //we iterate the splitters
  32. int i;
  33. int k = 0;
  34. int split_count= 0;
  35. //relevant: disp[1] - disp[3]
  36. for(i = 0; i < len; i++) {
  37. if(data[0] < splitters[split_count]) {
  38. split_count++;
  39. disp[k] = i;
  40. k++;
  41. }
  42. if(data[i] < splitters[split_count]) {
  43. //nothing to do
  44. } else if(data[i] >= splitters[split_count]) {
  45. //save index, inc split_count
  46. split_count++;
  47. disp[k] = i;
  48. k++;
  49. if(split_count == num_sp ) {
  50. //done
  51. break;
  52. }
  53. }
  54. }
  55. }
  56.  
  57. /**
  58. * Verify that all data is sorted globally
  59. */
  60. int verify_results_eff( int* arr, int len, int myrank, int nprocs ) {
  61. //we consider qsort to work correctly, so the first element in an array ist the smallest, and the last element is the biggest
  62. //we only check, if the last element of the array in p[i] is smaller than the first element of p[i+1]
  63. int smallest;
  64. smallest = arr[0];
  65. int biggest = arr[len-1];
  66. if(myrank == nprocs-1) {
  67. MPI_Recv(&biggest, 1, MPI_INTEGER, myrank -1, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  68. if(smallest > biggest) {
  69. return 0;
  70. }
  71. } else {
  72. MPI_Send(&biggest, 1, MPI_INTEGER, myrank +1, 0, MPI_COMM_WORLD);
  73. if(myrank != 0) {
  74. MPI_Recv(&biggest, 1, MPI_INTEGER, myrank -1, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  75. if(smallest > biggest) {
  76. return 0;
  77. }
  78. }
  79. }
  80. return 0;
  81. }
  82. int cmpfunc (const void * a, const void * b) {
  83. return ( *(int*)a - *(int*)b );
  84. }
  85. /**
  86. * Do the parallel sorting
  87. *
  88. * Note: The length of the local input array may change in this
  89. * call
  90. */
  91. void par_sort( int** orig_arr, int* orig_len, int myrank,
  92. int nprocs ) {
  93.  
  94. int i;
  95. /* Sort locally */
  96. qsort(*orig_arr, (size_t) *orig_len, sizeof(int), cmpfunc);
  97. /* Select local splitters */
  98. //p-1 elemts per process
  99. //index = [n(i+1)]/p
  100. //we have p-1 splitters for each process
  101. int* splitters = malloc(sizeof(int) * (nprocs-1));
  102. for(i = 0;i < nprocs-1;i++) {
  103. splitters[i] = orig_arr[(*orig_len * (i+1) ) / nprocs];
  104. }
  105. //each process stores its splitters in 'splitters' now
  106. /* Gather all the splitters on the root process */
  107. int* all_splitters = malloc(sizeof(int) * (nprocs *(nprocs -1)));
  108. //every process Sends its splitters to the root process
  109. MPI_Gather(splitters, (nprocs-1), MPI_INT, all_splitters, (nprocs-1), MPI_INT, 0, MPI_COMM_WORLD );
  110. //since we need an array of the same length for the global splitters, we dont free it yet
  111. //sort the Gathered splitters
  112. if(myrank == 0) {
  113. qsort(*all_splitters, (size_t) nprocs *(nprocs -1), sizeof(int), cmpfunc);
  114.  
  115. /* Select global splitters */
  116. //index = (p-1) * (i+1)
  117. for(i = 0; i < nprocs-1; i++) {
  118. splitters[i] = all_splitters[(nprocs-1) * (i+1)];
  119. }
  120. }
  121. MPI_Bcast(splitters, (nprocs-1), MPI_INT, 0, MPI_COMM_WORLD);
  122. //now the global splitters are in 'splitters' of every process
  123.  
  124. /* Redistribute parts */
  125. int* disp = malloc(sizeof(int) * nprocs);
  126. for(i = 0; i < nrpocs; i++) {
  127. disp[i] = 0;
  128. }
  129. // Call partition()
  130. partition(*orig_arr, *orig_len, *splitters,(nprocs-1), *disp);
  131. // Tell each process how many elments I Send to it
  132.  
  133. int* mess_len = 0;
  134. int x = 0;
  135. new_len = *orig_len;
  136. for(j = 1; j < nprocs; j++) {
  137. if((j-1)!=myrank) {
  138. for(i = 0; i < *orig_len; i++) {
  139. if(disp[j]== 0) {
  140. *mess_len = *orig_len-disp[j-1];
  141. //#mess_len elememts need to get Send to p[j-1]
  142. MPI_Send(*mess_len, 1, MPI_INTEGER, j-1, 0, MPI_COMM_WORLD);
  143. new_len = new_len - *mess_len;
  144. //allocate the Sending array
  145. int* send_arr = malloc(sizeof(int) * *mes_len);
  146. for(k=disp[j-1]; k < disp[j];k++) {
  147. send_arr[x] = orig_arr[k];
  148. x++;
  149. }
  150. MPI_Send(*send_arr, *mess_len, MPI_INTEGER, j-1, 1, MPI_COMM_WORLD);
  151. x = 0;
  152. break;
  153. }
  154. if(i == disp[j]) {
  155. //process j gets #i elements
  156. *mess_len = i -disp[j-1];
  157. //#mess_len elemets need to get Send to p[j-1]
  158. new_len = new_len - *mess_len;
  159. MPI_Send(*mess_len, 1, MPI_INTEGER, j-1, 0, MPI_COMM_WORLD);
  160. int* send_arr = malloc(sizeof(int) * mes_len);
  161. for(k=disp[j-1]; k < disp[j];k++) {
  162. send_arr[x] = orig_arr[k];
  163. x++;
  164. }
  165. MPI_Send(*send_arr, *mess_len, MPI_INTEGER, j-1, 1, MPI_COMM_WORLD);
  166. x = 0;
  167. if(j==nprocs-1 &&disp[j] != 0) {
  168. *mess_len = *orig_len-disp[j];
  169. new_len = new_len - *mess_len;
  170. //#mess_len elements need to get Send to p[j]
  171. MPI_Send(*mess_len, 1, MPI_INTEGER, j, 0, MPI_COMM_WORLD);
  172. int* send_arr = malloc(sizeof(int) * mes_len);
  173. for(k=disp[j-1]; k < disp[j];k++) {
  174. send_arr[x] = orig_arr[k];
  175. x++;
  176. }
  177. MPI_Send(*send_arr, *mess_len, MPI_INTEGER, j, 1, MPI_COMM_WORLD);
  178. x = 0;
  179. }
  180. break;
  181.  
  182. }
  183. }
  184. }
  185. }
  186. //receiving of the messages
  187. for(i = 0; i < nprocs; i++) {
  188. if(myrank == i) {
  189. //nothing to do
  190. } else {
  191. MPI_Recv(*mess_len, 1, MPI_INTEGER, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  192. *orig_arr = realloc(*orig_arr, sizeof(int)*(new_len + *mess_len));
  193. MPI_Recv(*orig_arr, *mess_len, MPI_INTEGER, i, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  194. }
  195.  
  196. }
  197. qsort(*orig_arr, (size_t) (new_len + *mess_len), sizeof(int), cmpfunc);
  198.  
  199.  
  200.  
  201. // Allocate array of proper size
  202. // Send one block to each process (blocks could also be empty)
  203.  
  204. /* Sort locally */
  205.  
  206. }
  207.  
  208. int main( int argc, char** argv ) {
  209.  
  210. int myrank, nprocs;
  211. MPI_Init( &argc, &argv );
  212. MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
  213. MPI_Comm_size( MPI_COMM_WORLD, &nprocs );
  214.  
  215. init_clock_time ();
  216.  
  217. /* Init the local part of the array */
  218. if( argc < 2 ) {
  219. printf( "Usage: %s <local_len>\n", argv[0] );
  220. exit( 1 );
  221. }
  222. int i, local_len = atoi( argv[1] );
  223. int* local_arr = malloc( local_len * sizeof(int) );
  224.  
  225. /* Randomize the input */
  226. srand( time(NULL) * myrank );
  227. for( i = 0; i < local_len; ++i )
  228. local_arr[i] = rand();
  229.  
  230. double start = get_clock_time();
  231.  
  232. /* Parallel sort */
  233. par_sort( &local_arr, &local_len, myrank, nprocs );
  234.  
  235. double elapsed = get_clock_time() - start;
  236.  
  237. /* Verify the results */
  238. int res = verify_results_eff( local_arr, local_len, myrank, nprocs );
  239. if( myrank == 0 )
  240. printf( "Sorted: %d\n", res );
  241.  
  242. /* Get timing - max across all ranks */
  243. double elapsed_global;
  244. MPI_Reduce( &elapsed, &elapsed_global, 1,
  245. MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD );
  246. if( myrank == 0 )
  247. printf( "Elapsed time (ms): %f\n", elapsed_global );
  248.  
  249. free( local_arr );
  250.  
  251. MPI_Finalize();
  252.  
  253. return 0;
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement