Advertisement
Guest User

Untitled

a guest
Dec 16th, 2017
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.32 KB | None | 0 0
  1. /****************************************************************************/
  2. /****************************************************************************/
  3. /** **/
  4. /** TU München - Institut für Informatik **/
  5. /** **/
  6. /** Copyright: Prof. Dr. Thomas Ludwig **/
  7. /** Andreas C. Schmidt **/
  8. /** **/
  9. /** File: partdiff-par.c **/
  10. /** **/
  11. /** Purpose: Partial differential equation solver for Gauß-Seidel and **/
  12. /** Jacobi method. **/
  13. /** **/
  14. /****************************************************************************/
  15. /****************************************************************************/
  16.  
  17. /* ************************************************************************ */
  18. /* Include standard header file. */
  19. /* ************************************************************************ */
  20. #define _POSIX_C_SOURCE 200809L
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <stdint.h>
  25. #include <inttypes.h>
  26. #include <math.h>
  27. #include <malloc.h>
  28. #include <sys/time.h>
  29. #include <mpi.h>
  30.  
  31. #include "partdiff-par.h"
  32.  
  33. //Konstanten
  34. const int ROOT_RANK = 0;
  35. const int TAG_PREVIOUS_ROW = 1;
  36. const int TAG_NEXT_ROW = 2;
  37.  
  38. //Parameter für die MPI-Kommunikation
  39. struct mpi_calc_arguments
  40. {
  41. //MPI-Parameter
  42. int rank; /*Aktueller rank*/
  43. int numberOfProcesses; /*Anzahl der Gesamtprozesse*/
  44. MPI_Status status; /*Der MPI-Status*/
  45.  
  46.  
  47. //Matrix-Paramter
  48. uint64_t startRowInTotalMatrix; /*Die Startreihe in der Gesamt-Matrix*/
  49. uint64_t matrixRows; /*Anzahl der Teilmatrix-Reihen*/
  50. uint64_t matrixColumns; /*Anzahl der Teilmatrix-Spalten*/
  51. };
  52.  
  53. struct calculation_arguments
  54. {
  55. uint64_t N; /* number of spaces between lines (lines=N+1) */
  56. uint64_t num_matrices; /* number of matrices */
  57. double h; /* length of a space between two lines */
  58. double ***Matrix; /* index matrix used for addressing M */
  59. double *M; /* two matrices with real values */
  60. };
  61.  
  62. struct calculation_results
  63. {
  64. uint64_t m;
  65. uint64_t stat_iteration; /* number of current iteration */
  66. double stat_precision; /* actual precision of all slaves in iteration */
  67. };
  68.  
  69. /* ************************************************************************ */
  70. /* Global variables */
  71. /* ************************************************************************ */
  72.  
  73. /* time measurement variables */
  74. struct timeval start_time; /* time when program started */
  75. struct timeval comp_time; /* time when calculation completed */
  76.  
  77.  
  78. /* ************************************************************************ */
  79. /* initVariables: Initializes some global variables */
  80. /* ************************************************************************ */
  81. static
  82. void
  83. initVariables (struct calculation_arguments* arguments, struct calculation_results* results, struct options const* options)
  84. {
  85. arguments->N = (options->interlines * 8) + 9 - 1;
  86. arguments->num_matrices = (options->method == METH_JACOBI) ? 2 : 1;
  87. arguments->h = 1.0 / arguments->N;
  88.  
  89. results->m = 0;
  90. results->stat_iteration = 0;
  91. results->stat_precision = 0;
  92. }
  93.  
  94. /* ************************************************************************ */
  95. /* freeMatrices: frees memory for matrices */
  96. /* ************************************************************************ */
  97. static
  98. void
  99. freeMatrices (struct calculation_arguments* arguments)
  100. {
  101. uint64_t i;
  102.  
  103. for (i = 0; i < arguments->num_matrices; i++)
  104. {
  105. free(arguments->Matrix[i]);
  106. }
  107.  
  108. free(arguments->Matrix);
  109. free(arguments->M);
  110. }
  111.  
  112. /* ************************************************************************ */
  113. /* allocateMemory () */
  114. /* allocates memory and quits if there was a memory allocation problem */
  115. /* ************************************************************************ */
  116. static
  117. void*
  118. allocateMemory (size_t size)
  119. {
  120. void *p;
  121.  
  122. if ((p = malloc(size)) == NULL)
  123. {
  124. printf("Speicherprobleme! (%" PRIu64 " Bytes angefordert)\n", size);
  125. exit(1);
  126. }
  127.  
  128. return p;
  129. }
  130.  
  131. /* ************************************************************************ */
  132. /* allocateMatrices: allocates memory for matrices */
  133. /* ************************************************************************ */
  134. static
  135. void
  136. allocateMatrices (struct calculation_arguments* arguments)
  137. {
  138. uint64_t i, j;
  139.  
  140. uint64_t const N = arguments->N;
  141.  
  142. arguments->M = allocateMemory(arguments->num_matrices * (N + 1) * (N + 1) * sizeof(double));
  143. arguments->Matrix = allocateMemory(arguments->num_matrices * sizeof(double**));
  144.  
  145. for (i = 0; i < arguments->num_matrices; i++)
  146. {
  147. arguments->Matrix[i] = allocateMemory((N + 1) * sizeof(double*));
  148.  
  149. for (j = 0; j <= N; j++)
  150. {
  151. arguments->Matrix[i][j] = arguments->M + (i * (N + 1) * (N + 1)) + (j * (N + 1));
  152. }
  153. }
  154. }
  155.  
  156. /* ************************************************************************ */
  157. /* allocateMatrices: allocates memory for matrices */
  158. /* ************************************************************************ */
  159. static
  160. void
  161. allocateMatricesMpi (struct calculation_arguments* arguments, struct mpi_calc_arguments* mpiArgs)
  162. {
  163. uint64_t i, j;
  164.  
  165. //Reihen für Prozess ermitteln
  166. const uint64_t rowsPerProcess = (arguments->N + 1) / mpiArgs->numberOfProcesses;
  167.  
  168. //Anzahl restlicher Reihen
  169. const int64_t remainRows = (arguments->N + 1) % mpiArgs->numberOfProcesses;
  170.  
  171. //Nur eine Reihe addieren, wenn erster oder letzter rank
  172. //Es wird nur Vor- oder Nachfolger benötigt
  173. if (mpiArgs->rank == ROOT_RANK || mpiArgs->rank == (mpiArgs->numberOfProcesses - 1))
  174. {
  175. mpiArgs->matrixRows = rowsPerProcess + 1;
  176. }
  177. //Zwei addieren, wegen letzte Reihe Vorgänger und erste Reihe Nachfolger
  178. else
  179. {
  180. mpiArgs->matrixRows = rowsPerProcess + 2;
  181. }
  182.  
  183. //Anzahl Columns ermitteln
  184. mpiArgs->matrixColumns = arguments->N + 1;
  185.  
  186. //Restliche Reihen aufteilen, wenn Prozessnummer kleiner Anzahl restlichen Reihen
  187. if (mpiArgs->rank < remainRows)
  188. {
  189. mpiArgs->matrixRows += 1;
  190. }
  191.  
  192. //Speicher für Matrixen reservieren
  193. arguments->M = allocateMemory(arguments->num_matrices * (mpiArgs->matrixRows * mpiArgs->matrixColumns) * sizeof(double));
  194. arguments->Matrix = allocateMemory(arguments->num_matrices * sizeof(double**));
  195.  
  196.  
  197. for (i = 0; i < arguments->num_matrices; i++)
  198. {
  199. arguments->Matrix[i] = allocateMemory((mpiArgs->matrixRows) * sizeof(double*));
  200.  
  201. for (j = 0; j < mpiArgs->matrixRows; j++)
  202. {
  203. arguments->Matrix[i][j] = arguments->M + (i * mpiArgs->matrixRows * mpiArgs->matrixColumns) + (j * mpiArgs->matrixColumns);
  204. }
  205. }
  206.  
  207. int actual_splitted_remain_rows = 0;
  208.  
  209. //Wenn Rank keine Extra-Reihe bekommen hat, dann müssen alle übergebliebenen Reihen hinzuaddiert werden
  210. if (mpiArgs->rank > remainRows)
  211. {
  212. actual_splitted_remain_rows = remainRows;
  213. }
  214. //Sonst müssen die bisherigen Extra-Reihen aufaddiert werden, die bisher aufgeteilt wurden (=Wert aktueller Rank)
  215. else
  216. {
  217. actual_splitted_remain_rows = mpiArgs->rank;
  218. }
  219.  
  220. //Root-Rank startet bei 1, weil die erste Reihe der Matrix nicht berechnet wird
  221. if(mpiArgs->rank == ROOT_RANK)
  222. {
  223. mpiArgs->startRowInTotalMatrix = 1;
  224. }
  225. else
  226. {
  227. //Startreihe des Prozesses in der Gesamt-Matrix berechnen
  228. mpiArgs->startRowInTotalMatrix = (rowsPerProcess * mpiArgs->rank) + actual_splitted_remain_rows;
  229. }
  230. }
  231.  
  232. /* ************************************************************************ */
  233. /* initMatrices: Initialize matrix/matrices and some global variables */
  234. /* ************************************************************************ */
  235. static
  236. void
  237. initMatrices (struct calculation_arguments* arguments, struct options const* options)
  238. {
  239. uint64_t g, i, j; /* local variables for loops */
  240.  
  241. uint64_t const N = arguments->N;
  242. double const h = arguments->h;
  243. double*** Matrix = arguments->Matrix;
  244.  
  245. /* initialize matrix/matrices with zeros */
  246. for (g = 0; g < arguments->num_matrices; g++)
  247. {
  248. for (i = 0; i <= N; i++)
  249. {
  250. for (j = 0; j <= N; j++)
  251. {
  252. Matrix[g][i][j] = 0.0;
  253. }
  254. }
  255. }
  256.  
  257. /* initialize borders, depending on function (function 2: nothing to do) */
  258. if (options->inf_func == FUNC_F0)
  259. {
  260. for (g = 0; g < arguments->num_matrices; g++)
  261. {
  262. for (i = 0; i <= N; i++)
  263. {
  264. Matrix[g][i][0] = 1.0 - (h * i);
  265. Matrix[g][i][N] = h * i;
  266. Matrix[g][0][i] = 1.0 - (h * i);
  267. Matrix[g][N][i] = h * i;
  268. }
  269.  
  270. Matrix[g][N][0] = 0.0;
  271. Matrix[g][0][N] = 0.0;
  272. }
  273. }
  274. }
  275.  
  276. /* ************************************************************************ */
  277. /* initMatrices: Initialize matrix/matrices and some global variables */
  278. /* ************************************************************************ */
  279. static
  280. void
  281. initMatricesMpi (struct calculation_arguments* arguments, struct options const* options, struct mpi_calc_arguments* mpiArgs)
  282. {
  283. uint64_t g, i, j; /* local variables for loops */
  284.  
  285. const uint64_t rows = mpiArgs->matrixRows;
  286. const uint64_t columns = mpiArgs->matrixColumns;
  287.  
  288. double const h = arguments->h;
  289. uint64_t const N = arguments->N;
  290. double*** Matrix = arguments->Matrix;
  291.  
  292. /* initialize matrix/matrices with zeros */
  293. for (g = 0; g < arguments->num_matrices; g++)
  294. {
  295. for (i = 1; i < rows; i++)
  296. {
  297. for (j = 0; j < columns; j++)
  298. {
  299. Matrix[g][i][j] = 0.0;
  300. }
  301. }
  302. }
  303.  
  304. /* initialize borders, depending on function (function 2: nothing to do) */
  305. if (options->inf_func == FUNC_F0)
  306. {
  307. uint64_t startRowInTotalMatrix = mpiArgs->startRowInTotalMatrix;
  308.  
  309. for (g = 0; g < arguments->num_matrices; g++)
  310. {
  311. //Initialisieren der Ränder
  312. for (uint64_t i = 0; i < rows - 1; i++)
  313. {
  314. Matrix[g][i][0] = 1.0 - (h * (startRowInTotalMatrix + i - 1));
  315. Matrix[g][i][N] = h * (startRowInTotalMatrix + i - 1);
  316. }
  317.  
  318. if (mpiArgs->rank == ROOT_RANK)
  319. {
  320. //Initialisieren der ersten Reihe
  321. for (uint64_t i = 0; i < columns; i++)
  322. {
  323. Matrix[g][0][i] = 1.0 - (h * i);
  324. }
  325. Matrix[g][0][N] = 0;
  326. }
  327. else if (mpiArgs->rank == (mpiArgs->numberOfProcesses - 1))
  328. {
  329. //Initialisieren der letzten Reihe
  330. for (uint64_t i = 0; i < columns; i++)
  331. {
  332. Matrix[g][rows - 1][i] = h * i;
  333. }
  334. Matrix[g][N][0] = 0;
  335. }
  336. }
  337. }
  338. }
  339.  
  340. /* ************************************************************************ */
  341. /* calculate: solves the equation */
  342. /* ************************************************************************ */
  343. static
  344. void
  345. calculate (struct calculation_arguments const* arguments, struct calculation_results* results, struct options const* options)
  346. {
  347. int i, j; /* local variables for loops */
  348. int m1, m2; /* used as indices for old and new matrices */
  349. double star; /* four times center value minus 4 neigh.b values */
  350. double residuum; /* residuum of current iteration */
  351. double maxresiduum; /* maximum residuum value of a slave in iteration */
  352.  
  353. int const N = arguments->N;
  354. double const h = arguments->h;
  355.  
  356. double pih = 0.0;
  357. double fpisin = 0.0;
  358.  
  359. int term_iteration = options->term_iteration;
  360.  
  361. /* initialize m1 and m2 depending on algorithm */
  362. if (options->method == METH_JACOBI)
  363. {
  364. m1 = 0;
  365. m2 = 1;
  366. }
  367. else
  368. {
  369. m1 = 0;
  370. m2 = 0;
  371. }
  372.  
  373. if (options->inf_func == FUNC_FPISIN)
  374. {
  375. pih = PI * h;
  376. fpisin = 0.25 * TWO_PI_SQUARE * h * h;
  377. }
  378.  
  379. while (term_iteration > 0)
  380. {
  381. double** Matrix_Out = arguments->Matrix[m1];
  382. double** Matrix_In = arguments->Matrix[m2];
  383.  
  384. maxresiduum = 0;
  385.  
  386. /* over all rows */
  387. for (i = 1; i < N; i++)
  388. {
  389. double fpisin_i = 0.0;
  390.  
  391. if (options->inf_func == FUNC_FPISIN)
  392. {
  393. fpisin_i = fpisin * sin(pih * (double)i);
  394. }
  395.  
  396. /* over all columns */
  397. for (j = 1; j < N; j++)
  398. {
  399. star = 0.25 * (Matrix_In[i-1][j] + Matrix_In[i][j-1] + Matrix_In[i][j+1] + Matrix_In[i+1][j]);
  400.  
  401. if (options->inf_func == FUNC_FPISIN)
  402. {
  403. star += fpisin_i * sin(pih * (double)j);
  404. }
  405.  
  406. if (options->termination == TERM_PREC || term_iteration == 1)
  407. {
  408. residuum = Matrix_In[i][j] - star;
  409. residuum = (residuum < 0) ? -residuum : residuum;
  410. maxresiduum = (residuum < maxresiduum) ? maxresiduum : residuum;
  411. }
  412.  
  413. Matrix_Out[i][j] = star;
  414. }
  415. }
  416.  
  417. results->stat_iteration++;
  418. results->stat_precision = maxresiduum;
  419.  
  420. /* exchange m1 and m2 */
  421. i = m1;
  422. m1 = m2;
  423. m2 = i;
  424.  
  425. /* check for stopping calculation depending on termination method */
  426. if (options->termination == TERM_PREC)
  427. {
  428. if (maxresiduum < options->term_precision)
  429. {
  430. term_iteration = 0;
  431. }
  432. }
  433. else if (options->termination == TERM_ITER)
  434. {
  435. term_iteration--;
  436. }
  437. }
  438.  
  439. results->m = m2;
  440. }
  441.  
  442. /* ************************************************************************ */
  443. /* calculate: solves the equation */
  444. /* ************************************************************************ */
  445. static
  446. void
  447. calculateMpiJacobi (struct calculation_arguments const* arguments, struct calculation_results *results, struct options const* options, struct mpi_calc_arguments* mpiArgs)
  448. {
  449. int i, j; /* local variables for loops */
  450. int m1, m2; /* used as indices for old and new matrices */
  451. double star; /* four times center value minus 4 neigh.b values */
  452. double residuum; /* residuum of current iteration */
  453. double maxresiduum; /* maximum residuum value of a slave in iteration */
  454. double const h = arguments->h;
  455. int columns = mpiArgs->matrixColumns;
  456. uint64_t startRowInTotalMatrix = mpiArgs->startRowInTotalMatrix;
  457.  
  458. //Die Startreihe ist immer 1, denn der Root-Rank soll die erste Matrixzeile nicht berechnen
  459. //und die anderen Prozesse haben in der ersten Reihe die letzte Reihe des Vorgängers gespeichert
  460. int startRow = 1;
  461.  
  462. //Letzte Reihe der Teilmatrix (über diese wird später nicht iteriert, weil sie entweder die erste Reihe des Nachfolgers ist
  463. //oder sie ist im letzten Rank die letzte Reihe der Gesamt-Matrix)
  464. int lastRow = mpiArgs->matrixRows - 1;
  465.  
  466. //Die Berechnung stimmen bei dem Root-Rank bzw letzten Rank nicht, weil der Root-Rank keinen Vorgänger und
  467. //der letzte keinen Nachfolger hat. Im Folgenden wird ein Senden bzw. Empfangen bei diesen Fällen jedoch verhindert,
  468. //sodass kein Fehler da durch aufritt.
  469. int nextTarget = mpiArgs->rank + 1;
  470. int previousTarget = mpiArgs->rank - 1;
  471.  
  472. double pih = 0.0;
  473. double fpisin = 0.0;
  474.  
  475. int term_iteration = options->term_iteration;
  476.  
  477. /* initialize m1 and m2 depending on algorithm */
  478. if (options->method == METH_JACOBI)
  479. {
  480. m1 = 0;
  481. m2 = 1;
  482. }
  483. else
  484. {
  485. m1 = 0;
  486. m2 = 0;
  487. }
  488.  
  489. if (options->inf_func == FUNC_FPISIN)
  490. {
  491. pih = PI * h;
  492. fpisin = 0.25 * TWO_PI_SQUARE * h * h;
  493. }
  494.  
  495. while (term_iteration > 0)
  496. {
  497. double** Matrix_Out = arguments->Matrix[m1];
  498. double** Matrix_In = arguments->Matrix[m2];
  499.  
  500. maxresiduum = 0;
  501.  
  502. MPI_Request request;
  503. /*** Senden und Empfangen der Zeilen ***/
  504.  
  505. //Wenn nicht Root-Rank, dann erste eigene Reihe an Vorgänger senden
  506. if (mpiArgs->rank != ROOT_RANK)
  507. {
  508. MPI_Isend(Matrix_In[1], mpiArgs->matrixColumns, MPI_DOUBLE, previousTarget, TAG_PREVIOUS_ROW, MPI_COMM_WORLD, &request);
  509. //MPI_Send(Matrix_In[1], mpiArgs->matrixColumns, MPI_DOUBLE, previousTarget, TAG_PREVIOUS_ROW, MPI_COMM_WORLD);
  510. }
  511.  
  512. //Wenn nicht letzter Rank, erst Reihe vom Nachfolger empfangen
  513. if (mpiArgs->rank != (mpiArgs->numberOfProcesses - 1))
  514. {
  515. MPI_Irecv(Matrix_In[lastRow], mpiArgs->matrixColumns, MPI_DOUBLE,nextTarget, TAG_PREVIOUS_ROW, MPI_COMM_WORLD, &request);
  516. //MPI_Recv(Matrix_In[lastRow], mpiArgs->matrixColumns, MPI_DOUBLE,nextTarget, TAG_PREVIOUS_ROW, MPI_COMM_WORLD, &mpiArgs->status);
  517. }
  518.  
  519. MPI_Wait(&request, &mpiArgs->status);
  520.  
  521. //Wenn nicht letzter Rank, dann letzte eigene Reihe an Nachfolger senden
  522. if (mpiArgs->rank != (mpiArgs->numberOfProcesses - 1))
  523. {
  524. MPI_Isend(Matrix_In[lastRow-1], mpiArgs->matrixColumns, MPI_DOUBLE, nextTarget, TAG_NEXT_ROW, MPI_COMM_WORLD, &request);
  525.  
  526. //MPI_Send(Matrix_In[lastRow - 1], mpiArgs->matrixColumns, MPI_DOUBLE, nextTarget, TAG_NEXT_ROW, MPI_COMM_WORLD);
  527. }
  528.  
  529. //Wenn nicht Root-Rank, dann letzte Reihe vom Vorgänger Empfangen
  530. if (mpiArgs->rank != ROOT_RANK)
  531. {
  532. MPI_Irecv(Matrix_In[0], mpiArgs->matrixColumns, MPI_DOUBLE,previousTarget, TAG_NEXT_ROW, MPI_COMM_WORLD, &request);
  533. //MPI_Recv(Matrix_In[0], mpiArgs->matrixColumns, MPI_DOUBLE,previousTarget, TAG_NEXT_ROW, MPI_COMM_WORLD, &mpiArgs->status);
  534.  
  535. }
  536. MPI_Wait(&request, &mpiArgs->status);
  537.  
  538. /* over all rows */
  539. for (i = startRow; i < lastRow; i++)
  540. {
  541. double fpisin_i = 0.0;
  542.  
  543. if (options->inf_func == FUNC_FPISIN)
  544. {
  545. fpisin_i = fpisin * sin(pih * (double)(startRowInTotalMatrix + i - startRow));
  546. }
  547.  
  548. /* over all columns */
  549. for (j = 1; j < (columns - 1); j++)
  550. {
  551. star = 0.25 * (Matrix_In[i-1][j] + Matrix_In[i][j-1] + Matrix_In[i][j+1] + Matrix_In[i+1][j]);
  552.  
  553. if (options->inf_func == FUNC_FPISIN)
  554. {
  555. star += fpisin_i * sin(pih * (double)j);
  556. }
  557.  
  558. if (options->termination == TERM_PREC || term_iteration == 1)
  559. {
  560. residuum = Matrix_In[i][j] - star;
  561. residuum = (residuum < 0) ? -residuum : residuum;
  562. maxresiduum = (residuum < maxresiduum) ? maxresiduum : residuum;
  563. }
  564.  
  565. Matrix_Out[i][j] = star;
  566. }
  567. }
  568.  
  569. results->stat_iteration++;
  570.  
  571. //Das MaxReisduum aller Prozesse ermitteln
  572. double maxresiduumOverAllProcesses;
  573. MPI_Allreduce(&maxresiduum, &maxresiduumOverAllProcesses, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
  574.  
  575. maxresiduum = maxresiduumOverAllProcesses;
  576. results->stat_precision = maxresiduum;
  577.  
  578. /* exchange m1 and m2 */
  579. i = m1;
  580. m1 = m2;
  581. m2 = i;
  582.  
  583. /* check for stopping calculation, depending on termination method */
  584. if (options->termination == TERM_PREC)
  585. {
  586. if (maxresiduum < options->term_precision)
  587. {
  588. term_iteration = 0;
  589. }
  590. }
  591. else if (options->termination == TERM_ITER)
  592. {
  593. term_iteration--;
  594. }
  595. MPI_Barrier(MPI_COMM_WORLD);
  596. }
  597.  
  598. results->m = m2;
  599. }
  600.  
  601.  
  602. /* ************************************************************************ */
  603. /* displayStatistics: displays some statistics about the calculation */
  604. /* ************************************************************************ */
  605. static
  606. void
  607. displayStatistics (struct calculation_arguments const* arguments, struct calculation_results const* results, struct options const* options)
  608. {
  609. int N = arguments->N;
  610. double time = (comp_time.tv_sec - start_time.tv_sec) + (comp_time.tv_usec - start_time.tv_usec) * 1e-6;
  611.  
  612. printf("Berechnungszeit: %f s \n", time);
  613. printf("Speicherbedarf: %f MiB\n", (N + 1) * (N + 1) * sizeof(double) * arguments->num_matrices / 1024.0 / 1024.0);
  614. printf("Berechnungsmethode: ");
  615.  
  616. if (options->method == METH_GAUSS_SEIDEL)
  617. {
  618. printf("Gauß-Seidel");
  619. }
  620. else if (options->method == METH_JACOBI)
  621. {
  622. printf("Jacobi");
  623. }
  624.  
  625. printf("\n");
  626. printf("Interlines: %" PRIu64 "\n",options->interlines);
  627. printf("Stoerfunktion: ");
  628.  
  629. if (options->inf_func == FUNC_F0)
  630. {
  631. printf("f(x,y) = 0");
  632. }
  633. else if (options->inf_func == FUNC_FPISIN)
  634. {
  635. printf("f(x,y) = 2pi^2*sin(pi*x)sin(pi*y)");
  636. }
  637.  
  638. printf("\n");
  639. printf("Terminierung: ");
  640.  
  641. if (options->termination == TERM_PREC)
  642. {
  643. printf("Hinreichende Genaugkeit");
  644. }
  645. else if (options->termination == TERM_ITER)
  646. {
  647. printf("Anzahl der Iterationen");
  648. }
  649.  
  650. printf("\n");
  651. printf("Anzahl Iterationen: %" PRIu64 "\n", results->stat_iteration);
  652. printf("Norm des Fehlers: %e\n", results->stat_precision);
  653. printf("\n");
  654. }
  655.  
  656. /****************************************************************************/
  657. /** Beschreibung der Funktion DisplayMatrix: **/
  658. /** **/
  659. /** Die Funktion DisplayMatrix gibt eine Matrix **/
  660. /** in einer "ubersichtlichen Art und Weise auf die Standardausgabe aus. **/
  661. /** **/
  662. /** Die "Ubersichtlichkeit wird erreicht, indem nur ein Teil der Matrix **/
  663. /** ausgegeben wird. Aus der Matrix werden die Randzeilen/-spalten sowie **/
  664. /** sieben Zwischenzeilen ausgegeben. **/
  665. /****************************************************************************/
  666. static
  667. void
  668. DisplayMatrix (struct calculation_arguments* arguments, struct calculation_results* results, struct options* options)
  669. {
  670. int x, y;
  671.  
  672. double** Matrix = arguments->Matrix[results->m];
  673.  
  674. int const interlines = options->interlines;
  675.  
  676. printf("Matrix:\n");
  677.  
  678. for (y = 0; y < 9; y++)
  679. {
  680. for (x = 0; x < 9; x++)
  681. {
  682. printf ("%7.4f", Matrix[y * (interlines + 1)][x * (interlines + 1)]);
  683. }
  684.  
  685. printf ("\n");
  686. }
  687.  
  688. fflush (stdout);
  689. }
  690.  
  691. /**
  692. * rank and size are the MPI rank and size, respectively.
  693. * from and to denote the global(!) range of lines that this process is responsible for.
  694. *
  695. * Example with 9 matrix lines and 4 processes:
  696. * - rank 0 is responsible for 1-2, rank 1 for 3-4, rank 2 for 5-6 and rank 3 for 7.
  697. * Lines 0 and 8 are not included because they are not calculated.
  698. * - Each process stores two halo lines in its matrix (except for ranks 0 and 3 that only store one).
  699. * - For instance: Rank 2 has four lines 0-3 but only calculates 1-2 because 0 and 3 are halo lines for other processes. It is responsible for (global) lines 5-6.
  700. */
  701. static
  702. void
  703. DisplayMatrixMpi (struct calculation_arguments* arguments, struct calculation_results* results, struct options* options, int rank, int size, int from, int to)
  704. {
  705. int const elements = 8 * options->interlines + 9;
  706.  
  707. int x, y;
  708. double** Matrix = arguments->Matrix[results->m];
  709. MPI_Status status;
  710.  
  711. /* first line belongs to rank 0 */
  712. if (rank == 0)
  713. from--;
  714.  
  715. /* last line belongs to rank size - 1 */
  716. if (rank + 1 == size)
  717. to++;
  718.  
  719. if (rank == 0)
  720. printf("Matrix:\n");
  721.  
  722. for (y = 0; y < 9; y++)
  723. {
  724. int line = y * (options->interlines + 1);
  725.  
  726. if (rank == 0)
  727. {
  728. /* check whether this line belongs to rank 0 */
  729. if (line < from || line > to)
  730. {
  731. /* use the tag to receive the lines in the correct order
  732. * the line is stored in Matrix[0], because we do not need it anymore */
  733. MPI_Recv(Matrix[0], elements, MPI_DOUBLE, MPI_ANY_SOURCE, 42 + y, MPI_COMM_WORLD, &status);
  734. }
  735. }
  736. else
  737. {
  738. if (line >= from && line <= to)
  739. {
  740. /* if the line belongs to this process, send it to rank 0
  741. * (line - from + 1) is used to calculate the correct local address */
  742. MPI_Send(Matrix[line - from + 1], elements, MPI_DOUBLE, 0, 42 + y, MPI_COMM_WORLD);
  743. }
  744. }
  745.  
  746. if (rank == 0)
  747. {
  748. for (x = 0; x < 9; x++)
  749. {
  750. int col = x * (options->interlines + 1);
  751.  
  752. if (line >= from && line <= to)
  753. {
  754. /* this line belongs to rank 0 */
  755. printf("%7.4f", Matrix[line][col]);
  756. }
  757. else
  758. {
  759. /* this line belongs to another rank and was received above */
  760. printf("%7.4f", Matrix[0][col]);
  761. }
  762. }
  763.  
  764. printf("\n");
  765. }
  766. }
  767.  
  768. fflush(stdout);
  769. }
  770.  
  771.  
  772. /* ************************************************************************ */
  773. /* main */
  774. /* ************************************************************************ */
  775. int
  776. main (int argc, char** argv)
  777. {
  778. struct options options;
  779. struct calculation_arguments arguments;
  780. struct calculation_results results;
  781.  
  782. struct mpi_calc_arguments mpiArgs;
  783.  
  784. MPI_Init(&argc, &argv);
  785. MPI_Comm_rank(MPI_COMM_WORLD, &mpiArgs.rank);
  786. MPI_Comm_size(MPI_COMM_WORLD, &mpiArgs.numberOfProcesses);
  787.  
  788. //AskParams um einen Parameter erweitert, damit nur der Root-Rank die Info am Anfang anzeigt
  789. AskParams(&options, argc, argv, mpiArgs.rank);
  790.  
  791. initVariables(&arguments, &results, &options);
  792.  
  793. //Nur wenn Jacobi und mehr als 1 Prozess
  794. if (options.method == METH_JACOBI && mpiArgs.numberOfProcesses > 1)
  795. {
  796. allocateMatricesMpi(&arguments, &mpiArgs);
  797. initMatricesMpi(&arguments, &options, &mpiArgs);
  798.  
  799. gettimeofday(&start_time, NULL);
  800. calculateMpiJacobi(&arguments, &results, &options, &mpiArgs);
  801. gettimeofday(&comp_time, NULL);
  802.  
  803. //Nur Root-Rank soll die Statistiken anzeigen
  804. if (mpiArgs.rank == ROOT_RANK)
  805. {
  806. displayStatistics(&arguments, &results, &options);
  807. }
  808.  
  809. DisplayMatrixMpi(&arguments, &results, &options, mpiArgs.rank, mpiArgs.numberOfProcesses, mpiArgs.startRowInTotalMatrix, mpiArgs.startRowInTotalMatrix + mpiArgs.matrixRows -3);
  810. }
  811. else
  812. {
  813. allocateMatrices(&arguments);
  814. initMatrices(&arguments, &options);
  815.  
  816. gettimeofday(&start_time, NULL);
  817. calculate(&arguments, &results, &options);
  818. gettimeofday(&comp_time, NULL);
  819.  
  820. displayStatistics(&arguments, &results, &options);
  821. DisplayMatrix(&arguments, &results, &options);
  822.  
  823. }
  824.  
  825. freeMatrices(&arguments);
  826. MPI_Finalize();
  827.  
  828. return 0;
  829. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement