MPI Fortran编译器优化错误

MPI Fortran编译器优化错误,fortran,mpi,compiler-optimization,Fortran,Mpi,Compiler Optimization,尽管已经编写了长时间的、高度并行的代码,其中包含复杂的三维数组的发送/接收,但这个包含二维整数数组的简单代码让我束手无策。我对stackoverflow进行了梳理,寻找可能的解决方案,发现了一个与我现在遇到的问题稍有相似的解决方案: 然而,解决方案似乎指出代码的循环段是重写内存部分的罪魁祸首。但这一次似乎表现得更为奇怪。也许是我疏忽了一些简单的细节。以下代码存在问题: program main implicit none include 'mpif.h' integer :: i, j i

尽管已经编写了长时间的、高度并行的代码,其中包含复杂的三维数组的发送/接收,但这个包含二维整数数组的简单代码让我束手无策。我对stackoverflow进行了梳理,寻找可能的解决方案,发现了一个与我现在遇到的问题稍有相似的解决方案:

然而,解决方案似乎指出代码的循环段是重写内存部分的罪魁祸首。但这一次似乎表现得更为奇怪。也许是我疏忽了一些简单的细节。以下代码存在问题:

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
当我使用没有标志的mpif90编译代码并在我的机器上使用mpirun-np 2运行它时,我在数组的前四个索引中得到以下值错误的输出:

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

但是,当我使用相同的编译器编译它时,但启用了-O3标志,我得到了正确的输出:

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

此错误与机器有关。这个问题只出现在我运行Ubuntu 14.04.2,使用OpenMPI 1.6.5的系统上

我在运行RedHat和CentOS的其他系统上尝试了这一点,代码在有无-O3标志的情况下运行良好。奇怪的是,这些机器使用的是OpenMPI-1.4的旧版本

我猜-O3标志正在执行一些奇怪的优化,即修改进程之间传递数组的方式

我还尝试了其他版本的数组分配。上面的代码使用显式形状数组。对于假定的形状和分配的阵列,我收到的结果是相同的,如果不是更奇怪的话,其中一些是seg断层。我尝试使用Valgrind跟踪这些seg故障的根源,但我仍然没有掌握让Valgrind在运行MPI程序时不给出误报的窍门

我相信,解决上述代码的性能差异将有助于我理解其他代码的愤怒


任何帮助都将不胜感激!这段代码真的让我怀疑我写的所有其他MPI代码是否都是正确的。

使用Fortran 90接口对MPI进行调用时发现调用
MPI\u 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)
这是因为状态变量
stVal
是一个
integer
标量,而不是
MPI\u status\u SIZE
的数组。到MPI_RECV的F77接口(
包括“mpif.h”
)是:

生成一个按预期工作的程序,并使用gfortran 5.1和OpenMPI 1.8.5进行测试


使用F90接口(
use mpi
vs
include“mpif.h”
)可以让编译器在编译时检测不匹配的参数,而不是产生混乱的运行时问题。

这是一个非常常见的错误。不幸的是,即使使用mpi模块,接口也往往不明确(可能是直接复制?)@casey:非常感谢!但在gfortran 4.8.2和ompi 1.6.5上,切换到“使用mpi”并不会给我带来错误。我仍然很好奇优化的旗帜是如何掩盖它的。@RoshanSam读了赫里斯托·伊利耶夫在我的链接中写的内容。优化会更改堆栈上变量的位置。他还解释了为什么即使使用
使用mpi
@VladimirF,您也不会收到任何警告。他的评论很有帮助,谢谢。。我很惊讶stackoverflow在我反复寻找解决方案时没有指出上述问题。可能是因为虽然潜在的问题是相同的,但症状是不同的。再次感谢!:)我可能会将这些问题标记为重复问题。有反对意见吗?
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
integer :: rank, ierr, stVal
integer :: rank, ierr, stVal(mpi_status_size)