fortran - descargar - mpi version
Error de optimización del compilador de Fortran de MPI (1)
El uso de la interfaz Fortran 90 para MPI revela una falta de coincidencia en su llamada a MPI_RECV
call MPI_RECV(prntMat(1:10, 1:10), 100, MPI_INTEGER, 1, 1, MPI_COMM_WORLD, stVal, ierr)
1
Error: There is no specific subroutine for the generic ‘mpi_recv’ at (1)
Esto se debe a que la variable de estado stVal
es un escalar integer
, en lugar de una matriz de MPI_STATUS_SIZE
. La interfaz F77 ( include ''mpif.h''
) a MPI_RECV
es:
INCLUDE ’mpif.h’ MPI_RECV(BUF, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR) <type> BUF(*) INTEGER COUNT, DATATYPE, SOURCE, TAG, COMM INTEGER STATUS(MPI_STATUS_SIZE), IERROR
Cambiando
integer :: rank, ierr, stVal
a
integer :: rank, ierr, stVal(mpi_status_size)
produce un programa que funciona como se espera, probado con gfortran 5.1 y OpenMPI 1.8.5.
El uso de la interfaz F90 ( use mpi
vs include "mpif.h"
) permite al compilador detectar los argumentos no coincidentes en tiempo de compilación en lugar de generar problemas de tiempo de ejecución confusos.
Esta pregunta ya tiene una respuesta aquí:
- MPI_Recv cambia el valor de la respuesta del conteo 1
A pesar de haber escrito códigos largos, muy paralelizados con complicados envíos / recepciones sobre matrices tridimensionales, este código simple con una matriz bidimensional de enteros me ha puesto a mi ingenio. Combiné stackoverflow para posibles soluciones y encontré uno que se parecía un poco al problema que estoy teniendo:
Boost.MPI: ¡Lo que se recibe no es lo que se envió!
Sin embargo, las soluciones parecen apuntar al segmento de bucle del código como el culpable de sobrescribir secciones de la memoria. Pero este parece actuar aún más extraño. Tal vez es una descuidada supervisión de algunos detalles simples de mi parte. El problema es con el siguiente código:
program main
implicit none
include ''mpif.h''
integer :: i, j
integer :: counter, offset
integer :: rank, ierr, stVal
integer, dimension(10, 10) :: passMat, prntMat !! passMat CONTAINS VALUES TO BE PASSED TO prntMat
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
counter = 0
offset = (rank + 1)*300
do j = 1, 10
do i = 1, 10
prntMat(i, j) = 10 !! prntMat OF BOTH RANKS CONTAIN 10
passMat(i, j) = offset + counter !! passMat OF rank=0 CONTAINS 300..399 AND rank=1 CONTAINS 600..699
counter = counter + 1
end do
end do
if (rank == 1) then
call MPI_SEND(passMat(1:10, 1:10), 100, MPI_INTEGER, 0, 1, MPI_COMM_WORLD, ierr) !! SEND passMat OF rank=1 to rank=0
else
call MPI_RECV(prntMat(1:10, 1:10), 100, MPI_INTEGER, 1, 1, MPI_COMM_WORLD, stVal, ierr)
do i = 1, 10
print *, prntMat(:, i)
end do
end if
call MPI_FINALIZE(ierr)
end program main
Cuando compilo el código con mpif90 sin banderas y lo ejecuto en mi máquina con mpirun -np 2, obtengo la siguiente salida con valores incorrectos en los primeros cuatro índices de la matriz:
0 0 400 0 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
Sin embargo, cuando lo compilo con el mismo compilador pero con el indicador -O3 activado, obtengo el resultado correcto:
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
Este error depende de la máquina. Este problema aparece solo en mi sistema que ejecuta Ubuntu 14.04.2, usando OpenMPI 1.6.5
Intenté esto en otros sistemas que ejecutan RedHat y CentOS y el código funcionaba bien con y sin el distintivo -O3. Curiosamente esas máquinas usan una versión anterior de OpenMPI - 1.4
Supongo que la bandera -O3 está realizando una optimización impar que está modificando la manera en que las matrices se pasan entre los procesos.
También probé otras versiones de asignación de matriz. El código anterior usa matrices de formas explícitas. Con la forma asumida y las matrices asignadas, recibo igualmente, si no más, resultados extraños, con algunos de ellos seg-faulting. Intenté usar Valgrind para rastrear el origen de estas seg-faults, pero todavía no me he acostumbrado a que Valgrind no proporcione falsos positivos cuando se ejecuta con programas MPI.
Creo que resolver la diferencia en el rendimiento del código anterior también me ayudará a entender los berrinches de mis otros códigos.
¡Cualquier ayuda sería muy apreciada! Este código realmente me ha hecho cuestionar si todos los otros códigos MPI que escribí son en absoluto sonido.