MPI Fortran编译器优化错误[重复]

Posted

技术标签:

【中文标题】MPI Fortran编译器优化错误[重复]【英文标题】:MPI Fortran compiler optimization error [duplicate] 【发布时间】:2015-05-29 18:53:39 【问题描述】:

尽管编写了长且高度并行化的代码,并在三维数组上进行了复杂的发送/接收,但这个包含二维整数数组的简单代码让我大吃一惊。我梳理了 *** 以寻找可能的解决方案,发现一个与我遇到的问题略有相似的解决方案:

Boost.MPI: What's received isn't what was sent!

但是,解决方案似乎将循环代码段作为覆盖内存部分的罪魁祸首。但这一个似乎表现得更奇怪。也许这是我对一些简单细节的粗心疏忽。问题在于以下代码:

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 标志正在执行一些奇怪的优化,正在修改进程之间传递数组的方式。

我还尝试了其他版本的数组分配。上面的代码使用了显式的形状数组。对于假定的形状和分配的数组,如果不是更奇怪的结果,我会收到同样的结果,其中一些是段错误。我尝试使用 Valgrind 来追踪这些 seg-fault 的起源,但我仍然没有掌握让 Valgrind 在运行 MPI 程序时不给出误报的窍门。

我相信解决上述代码的性能差异也将有助于我理解其他代码的脾气。

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

【问题讨论】:

【参考方案1】:

对 MPI 使用 Fortran 90 接口显示您对 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)

这是因为状态变量stVal 是一个integer 标量,而不是MPI_STATUS_SIZE 的数组。 F77接口(@98​​7654327@)转MPI_RECV为:

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)

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

使用 F90 接口(@98​​7654332@ 与 include "mpif.h")让编译器可以在编译时检测不匹配的参数,而不是产生令人困惑的运行时问题。

【讨论】:

一个非常常见的错误。不幸的是,即使使用 mpi 模块 ***.com/questions/13049648/…,接口通常也不明确(可能是直接复制?) @casey:非常感谢!但是在 gfortran 4.8.2、ompi 1.6.5 上切换到“使用 mpi”并没有引发错误。而且我仍然很好奇优化标志是如何掩盖它的。 @RoshanSam 阅读了 Hristo Illiev 在我的链接中写的内容。优化改变了位于堆栈上的变量的位置。他还解释了为什么即使使用use mpi 也不会收到任何警告。 @VladimirF 他的 cmets 很有帮助,谢谢.. 当我反复寻找解决方案时,*** 没有指出上述问题,这让我很惊讶。可能是因为虽然根本问题相同,但症状不同。再次感谢! :) 我可能会将这些问题标记为重复。有异议吗?

以上是关于MPI Fortran编译器优化错误[重复]的主要内容,如果未能解决你的问题,请参考以下文章

mpifort -DMPI 编译错误:派生类型“mpi_status”用作实际参数。适用于英特尔 Fortran,但不适用于 GNU Fortran

OpenACC + MPI Fortran 程序入门

将 mpi 消息从 c++ 代码发送到 fortran 90 代码

Fortran 和 MPI 的良好分析器

Fortran 90 和 MPI 错误

Fortran 2008 - 条件编译[重复]