Guest User

Untitled

a guest
Jun 25th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.95 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <omp.h>
  4. #include <mpi.h>
  5. #include <time.h>
  6. #include <math.h>
  7. #define MIN(x, y) (((x) < (y)) ? (x) : (y))
  8.  
  9. double sampleTime()
  10. {
  11. struct timespec tv;
  12. clock_gettime(CLOCK_MONOTONIC, &tv);
  13. return ((double)tv.tv_sec + ((double)tv.tv_nsec) / 1000000000.0);
  14. }
  15.  
  16. int main(int argc, char *argv[])
  17. {
  18. float t = 0.0;
  19. FILE *fp;
  20. int x = 0, y = 0, i = 0, j = 0,
  21. cantProcesosAncho = 0, cantProcesosAlto = 0,
  22. posi = 0, posj = 0,
  23. alto = 0, ancho = 0,
  24. restoFilas = 0, restoColumnas = 0;
  25.  
  26. int lado, repete, rank, size,
  27. rankVecinoSup = -1, rankVecinoInf = -1, rankVecinoIzq = -1, rankVecinoDer = -1;
  28.  
  29. float **matrizLocal, **matrizCopia, **punteroAux;
  30.  
  31. if (argc < 3)
  32. {
  33. printf("ingrese 2 argumentos - tamanio de la matriz y cantidad de pasos\n");
  34. exit(-1);
  35. }
  36. lado = atoi(argv[1]);
  37. repete = atoi(argv[2]);
  38.  
  39. MPI_Init(&argc, &argv);
  40. MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  41. MPI_Comm_size(MPI_COMM_WORLD, &size);
  42.  
  43. MPI_Request requestVecinoSup;
  44. MPI_Request requestVecinoInf;
  45. MPI_Request requestVecinoDer;
  46. MPI_Request requestVecinoIzq;
  47. MPI_Request request;
  48. MPI_Status status;
  49. MPI_Status status1;
  50. MPI_Status status2;
  51. MPI_Status status3;
  52.  
  53. // ------------------------------------------------------------------- CALCULO DE DISTRIBUCIÖN -------------------------------------------------------------------------------- //
  54. float raizSize = 0;
  55. raizSize = sqrt(size);
  56.  
  57. for (i = 1; i <= raizSize; i++)
  58. {
  59. if (size % i == 0)
  60. {
  61. cantProcesosAncho = i;
  62. }
  63. }
  64. /* El resultado siguiente siempre es entero ya que cantProcesos ancho es un divisor de size */
  65. cantProcesosAlto = size / cantProcesosAncho;
  66. int nroProc = 0;
  67. int mapaProcesos[cantProcesosAlto][cantProcesosAncho];
  68.  
  69. // si cantProcesosAncho == 1 , entonces la distribucion sera por filas, sino sera una cuadricula de n x m
  70. if (cantProcesosAncho > 1)
  71. { //defino mi mapa de procesos solo utilizado para distribucion matricial
  72. for (i = 0; i < cantProcesosAlto; i++)
  73. {
  74. for (j = 0; j < cantProcesosAncho; j++)
  75. {
  76. mapaProcesos[i][j] = nroProc;
  77. if (rank == nroProc)
  78. {
  79. posi = i;
  80. posj = j;
  81. }
  82. nroProc++;
  83. }
  84. }
  85. if (posi > 0)
  86. { //chequeo que el proceso no este en la 1er fila del mapaProcesos
  87. rankVecinoSup = rank - cantProcesosAncho;
  88. }
  89. if ((posi + 1) < cantProcesosAlto)
  90. { //chequeo que el proceso no este en la ultima fila del mapaProcesos
  91. rankVecinoInf = rank + cantProcesosAncho;
  92. }
  93. if (posj > 0)
  94. { //chequeo que el proceso no este en la 1er columna del mapaProcesos
  95. rankVecinoIzq = rank - 1;
  96. }
  97. if ((posj + 1) < cantProcesosAncho)
  98. { //chequeo que el proceso no este en la ultima columna del mapaProcesos
  99. rankVecinoDer = rank + 1;
  100. }
  101. }
  102. else
  103. { //Asigno los valores de los ranks vecinos para distribucion lista
  104. if (rank > 0) // chequeamos que no sea en el proceso rank = 0
  105. {
  106. rankVecinoSup = rank - 1;
  107. }
  108. if (rank < (size - 1)) // chequeamos que no sea el proceso rank = size -1
  109. {
  110. rankVecinoInf = rank + 1;
  111. }
  112. }
  113. // -------------------------------------------------------------- FIN CALCULO DE DISTRIBUCIÖN ------------------------------------------------------------------------------ //
  114. // ------------------------------------------------------------------- ASIGNACION DE MEMORIA ------------------------------------------------------------------------------- //
  115.  
  116. alto = (lado / cantProcesosAlto);
  117. restoFilas = lado % cantProcesosAlto;
  118. if (cantProcesosAncho == 1)
  119. { //Defino variables para saber cuanta memoria reservar
  120. ancho = lado;
  121.  
  122. if (rank < restoFilas)
  123. { //Estiro el alto en caso de que hayan sobrado filas, para abarcar esas filas sobrantes
  124. alto = alto + 1;
  125. }
  126. }
  127. else
  128. { // Reservo espacio en forma de submatrices
  129. ancho = lado / cantProcesosAncho;
  130. restoColumnas = lado % cantProcesosAncho;
  131.  
  132. //estiro las filas o columnas que sean menores al numero de filas y columnas sobrantes.
  133. if (posj < restoColumnas)
  134. {
  135. ancho = ancho + 1;
  136. }
  137. if (posi < restoFilas)
  138. {
  139. alto = alto + 1;
  140. }
  141. }
  142. // reservo 2 arreglos para los datos de las columnas de los vecinos
  143. float columnaVecinoIzq[alto], columnaVecinoDer[alto],
  144. filaVecinoSup[ancho], filaVecinoInf[ancho];
  145.  
  146. matrizLocal = malloc(alto * sizeof(float *));
  147. matrizCopia = malloc(alto * sizeof(float *));
  148. matrizLocal[0] = malloc(sizeof(float) * ancho * alto);
  149. matrizCopia[0] = malloc(sizeof(float) * ancho * alto);
  150. for (i = 1; i < alto; i++)
  151. {
  152. matrizLocal[i] = matrizLocal[0] + ancho * i;
  153. matrizCopia[i] = matrizCopia[0] + ancho * i;
  154. }
  155.  
  156. // -------------------------------------------------------------- FIN ASIGNACION DE MEMORIA ------------------------------------------------------------------------------ //
  157. for (x = 0; x < alto; x++)
  158. {
  159. for (y = 0; y < ancho; y++)
  160. {
  161. matrizLocal[x][y] = 0.0;
  162. matrizCopia[x][y] = 0.0; //Inicializamos la matriz copia con ceros
  163. }
  164. }
  165.  
  166. int columnaGlobal = 0, filaGlobal = 0;
  167. /*inicializo el fragmento de la matriz que le corresponda a cada proceso*/
  168. // Si la distribucion es por filas
  169. if (cantProcesosAncho == 1)
  170. {
  171. // printf("Filas\n");
  172. //Determinamos en que fila de la matriz global comienza nuestra porcion local de la matriz
  173. filaGlobal = (rank * alto) + MIN(restoFilas, rank);
  174. // printf("alto, %d, ancho, %d\n", alto, ancho);
  175. // printf("filaglobal %d \n", filaGlobal);
  176.  
  177. for (x = 0; x < alto; x++)
  178. {
  179. for (y = 0; y < ancho; y++)
  180. {
  181. matrizLocal[x][y] = x * (x + filaGlobal) * (lado - (x + filaGlobal) - 1) * y * (lado - y - 1);
  182. }
  183. }
  184. }
  185. //Si la distribucion es por submatrices
  186. else
  187. {
  188. // printf("SubMatrices\n");
  189. filaGlobal = (posi * alto) + MIN(restoFilas, posi);
  190. columnaGlobal = (posj * ancho) + MIN(restoColumnas, posj);
  191. // printf("rank:%d filaGlobal:%d columnaGlobal:%d\n", rank, filaGlobal, columnaGlobal);
  192. // printf("rank:%d posi:%d posj:%d\n", rank, posi, posj);
  193. /* Verificado, Esta bien! Algunos valores de bordes tienen valores distintos de 0 xq lados
  194. piso durante la ejecucion de pasos al parecer.*/
  195. for (x = 0; x < alto; x++)
  196. {
  197. for (y = 0; y < ancho; y++)
  198. {
  199. matrizLocal[x][y] = (x + filaGlobal) * (lado - (x + filaGlobal) - 1) * (y + columnaGlobal) * (lado - (y + columnaGlobal) - 1);
  200. }
  201. }
  202. }
  203.  
  204. // --------------------------------------------------------------------FIN INICIALIZACION ----------------------------------------------------------------------------------- //
  205. if (rank == 0)
  206. {
  207. t = sampleTime();
  208. }
  209. // -----------------------------------------------------------------------CALCULO -------------------------------------------------------------------------------------------- //
  210. //Si la distribución es matricial declaro el tipo de dato para los buffers
  211. MPI_Datatype buffer;
  212. MPI_Type_vector(alto, 1, ancho, MPI_FLOAT, &buffer);
  213. MPI_Type_commit(&buffer);
  214. /*MPI_Type_commit( ) separates the datatypes you really want to save and use from the
  215. intermediate ones that are scaffolded on the way to some very complex datatype.*/
  216.  
  217. for (i = 0; i < repete; i++)
  218. {
  219. if (rankVecinoSup != -1)
  220. { // Enviamos la fila superior al vecino sup.
  221. MPI_Isend(&matrizLocal[0][0], ancho, MPI_FLOAT, rankVecinoSup, 0, MPI_COMM_WORLD, &request);
  222. MPI_Irecv(filaVecinoSup, ancho, MPI_FLOAT, rankVecinoSup, 1, MPI_COMM_WORLD, &requestVecinoInf);
  223. }
  224. if (rankVecinoInf != -1)
  225. { // Enviamos la fila superior al vecino sup.
  226.  
  227. MPI_Isend(&matrizLocal[alto - 1][0], ancho, MPI_FLOAT, rankVecinoInf, 1, MPI_COMM_WORLD, &request);
  228. MPI_Irecv(filaVecinoInf, ancho, MPI_FLOAT, rankVecinoInf, 0, MPI_COMM_WORLD, &requestVecinoSup);
  229. }
  230. if (rankVecinoIzq != -1)
  231. { // Enviamos la columna izquierda al vecino izquierdo.
  232. MPI_Isend(&matrizLocal[0][0], 1, buffer, rankVecinoIzq, 2, MPI_COMM_WORLD, &request);
  233. MPI_Irecv(columnaVecinoIzq, alto, MPI_FLOAT, rankVecinoIzq, 3, MPI_COMM_WORLD, &requestVecinoDer);
  234. }
  235. if (rankVecinoDer != -1)
  236. {
  237. MPI_Isend(&matrizLocal[0][ancho - 1], 1, buffer, rankVecinoDer, 3, MPI_COMM_WORLD, &request);
  238. MPI_Irecv(columnaVecinoDer, alto, MPI_FLOAT, rankVecinoDer, 2, MPI_COMM_WORLD, &requestVecinoIzq);
  239. }
  240.  
  241. //Calculo los elementos del centro, los que no tienen interacciones con los vecinos
  242. for (x = 1; x < (alto - 1); x++)
  243. {
  244. for (y = 1; y < (ancho - 1); y++)
  245. {
  246. matrizCopia[x][y] = (matrizLocal[x][y]) +
  247. (0.1 * (matrizLocal[x + 1][y] + matrizLocal[x - 1][y] - (2 * matrizLocal[x][y]))) +
  248. (0.1 * (matrizLocal[x][y + 1] + matrizLocal[x][y - 1] - (2 * matrizLocal[x][y])));
  249. }
  250. }
  251. // printf("rank:%d top:%d bot:%d izq:%d der:%d\n",rank, rankVecinoSup,rankVecinoInf,rankVecinoIzq,rankVecinoDer);
  252. //Con ese print me aseguré de que todos los procesos tienen correctamente asignados sus vecinos y -1 cuando no tienen
  253. //Por lo tanto el error esta al enviar mensajes. Xq algunos bordes no se computan.
  254.  
  255. // printf("%d%d%d%d",sizeof(columnaVecinoIzq),sizeof(columnaVecinoDer),sizeof(filaVecinoSup),sizeof(filaVecinoInf));
  256. //--------------------------------------Bordes-------------------------------------
  257. if (rankVecinoSup != -1)
  258. {
  259. MPI_Wait(&requestVecinoInf, &status);
  260. for (y = 1; y < ancho - 1; y++)
  261. {
  262. matrizCopia[0][y] = (matrizLocal[0][y]) +
  263. (0.1 * (filaVecinoSup[y] + matrizLocal[1][y] - (2 * matrizLocal[0][y]))) +
  264. (0.1 * (matrizLocal[0][y + 1] + matrizLocal[0][y - 1] - (2 * matrizLocal[0][y])));
  265. }
  266. }
  267. if (rankVecinoInf != -1)
  268. {
  269. MPI_Wait(&requestVecinoSup, &status);
  270. for (y = 1; y < ancho - 1; y++)
  271. {
  272. matrizCopia[alto - 1][y] = (matrizLocal[alto - 1][y]) +
  273. (0.1 * (matrizLocal[alto - 2][y] + filaVecinoInf[y] - (2 * matrizLocal[alto - 1][y]))) +
  274. (0.1 * (matrizLocal[alto - 1][y + 1] + matrizLocal[alto - 1][y - 1] - (2 * matrizLocal[alto - 1][y])));
  275. }
  276. }
  277. if (rankVecinoIzq != -1)
  278. {
  279. MPI_Wait(&requestVecinoDer, &status);
  280. for (x = 1; x < alto - 1; x++)
  281. {
  282. matrizCopia[x][0] = (matrizLocal[x][0]) +
  283. (0.1 * (matrizLocal[x + 1][0] + matrizLocal[x - 1][0] - (2 * matrizLocal[x][0]))) +
  284. (0.1 * (matrizLocal[x][1] + columnaVecinoIzq[x] - (2 * matrizLocal[x][0])));
  285. }
  286. }
  287. if (rankVecinoDer != -1)
  288. {
  289. MPI_Wait(&requestVecinoIzq, &status);
  290. for (x = 1; x < alto - 1; x++)
  291. {
  292. matrizCopia[x][ancho - 1] = (matrizLocal[x][ancho - 1]) +
  293. (0.1 * (matrizLocal[x + 1][ancho - 1] + matrizLocal[x - 1][ancho - 1] - (2 * matrizLocal[x][ancho - 1]))) +
  294. (0.1 * (columnaVecinoDer[x] + matrizLocal[x][ancho - 2] - (2 * matrizLocal[x][ancho - 1])));
  295. }
  296. }
  297.  
  298. //------------------------------Esquinas-------------------------------
  299. if (rankVecinoSup != -1)
  300. {
  301. // CALCULAMOS LA ESQUINA SUPERIOR IZQUIERDA DE LA SUBMATRIZ
  302. if (rankVecinoIzq != -1)
  303. {
  304. matrizCopia[0][0] = matrizLocal[0][0] +
  305. (0.1 * (matrizLocal[0][1] + columnaVecinoIzq[0] - (2 * matrizLocal[0][0]))) +
  306. (0.1 * (filaVecinoSup[0] + matrizLocal[1][0] - (2 * matrizLocal[0][0])));
  307. }
  308. // CALCULAMOS LA ESQUINA SUPERIOR DERECHA DE LA SUBMATRIZ
  309. if (rankVecinoDer != -1)
  310. {
  311. matrizCopia[0][ancho - 1] = matrizLocal[0][ancho - 1] +
  312. (0.1 * (columnaVecinoDer[0] + matrizLocal[0][ancho - 2] - (2 * matrizLocal[0][ancho - 1]))) +
  313. (0.1 * (filaVecinoSup[0] + matrizLocal[1][ancho - 1] - (2 * matrizLocal[0][ancho - 1])));
  314. }
  315. }
  316. if (rankVecinoInf != -1)
  317. {
  318. // CALCULAMOS LA ESQUINA INFERIOR IZQUIERDA DE LA SUBMATRIZ
  319. if (rankVecinoIzq != -1)
  320. {
  321. matrizCopia[alto - 1][0] = matrizLocal[alto - 1][0] +
  322. (0.1 * (matrizLocal[alto - 1][1] + columnaVecinoIzq[alto - 1] - (2 * matrizLocal[alto - 1][0]))) +
  323. (0.1 * (matrizLocal[alto - 2][0] + filaVecinoInf[0] - (2 * matrizLocal[alto - 1][0])));
  324. }
  325. // CALCULAMOS LA ESQUINA INFERIOR DERECHA DE LA SUBMATRIZ
  326. if (rankVecinoDer != -1)
  327. {
  328. matrizCopia[alto - 1][ancho - 1] = matrizLocal[alto - 1][ancho - 1] +
  329. (0.1 * (columnaVecinoDer[alto - 1] + matrizLocal[alto - 1][ancho - 2] - (2 * matrizLocal[alto - 1][ancho - 1]))) +
  330. (0.1 * (matrizLocal[alto - 2][ancho - 1] + filaVecinoInf[ancho - 1] - (2 * matrizLocal[alto - 1][ancho - 1])));
  331. }
  332. }
  333.  
  334. MPI_Barrier(MPI_COMM_WORLD);
  335.  
  336. //Intercambio de matrices
  337. punteroAux = matrizLocal;
  338. matrizLocal = matrizCopia;
  339. matrizCopia = punteroAux;
  340. }
  341. // -----------------------------------------------------------------------FIN______CALCULO ------------------------------------------------------------------------------------ //
  342. if (rank == 0)
  343. {
  344. float TiempoTotal = sampleTime() - t;
  345. printf("tiempo transcurrido: %f segundos\n", TiempoTotal);
  346. }
  347. // Imprimo en el archivo
  348. char nombre[30];
  349. sprintf(nombre, "subgrid_%d_%d.out", posi, posj);
  350.  
  351. fp = fopen(nombre, "w+");
  352. for (x = 0; x < alto; x++)
  353. {
  354. for (y = 0; y < ancho; y++)
  355. {
  356. fprintf(fp, "%8.3f ", matrizLocal[x][y]);
  357. }
  358. fprintf(fp, "\n");
  359. }
  360. fprintf(fp, "\n");
  361. fclose(fp);
  362.  
  363. MPI_Finalize();
  364. return 0;
  365. }
Add Comment
Please, Sign In to add comment