我遇到以下基本代码的问题:
program foo
use mpi
implicit none
type bartype
real(8) :: x
integer :: i
end type bartype
integer :: mpi_bar_type
integer :: &
count=2, &
blocklengths(2)=(/1,1/), &
types(2)=(/mpi_double_precision, &
mpi_integer/)
integer(kind=mpi_address_kind) :: displs(2)
type(bartype) :: bar, bararray(4)
integer :: rank, ierr, i, test(4), addr0
call mpi_init(ierr)
call mpi_comm_rank(mpi_comm_world, rank, ierr)
call mpi_get_address(bar, addr0)
call mpi_get_address(bar%x, displs(1))
call mpi_get_address(bar%i, displs(2))
do i=1,2
displs(i)=displs(i)-addr0
enddo
call mpi_type_create_struct(2,blocklengths,displs,types,mpi_bar_type,ierr)
call mpi_type_commit(mpi_bar_type,ierr)
bararray(:)%x=rank
bararray(:)%i=rank
test(:)=rank
call mpi_bcast(test, 4, mpi_integer, 0, mpi_comm_world,ierr)
call mpi_bcast(bararray, 4, mpi_bar_type, 0, mpi_comm_world,ierr)
call mpi_finalize(ierr)
end program foo
我在派生类型Bcast(使用intelMPI和openMPI)上获得了段错误,在调试器(DDT)中,据说这可能是对齐问题...
我已经看过this帖子,问题似乎是一样的,但我仍然没有解决方案......
感谢您的帮助!
答案 0 :(得分:0)
试试这个:
program foo
implicit none
include 'mpif.h'
type bartype
real(8) :: x
integer :: i
end type bartype
integer :: mpi_bar_type
integer :: &
count=4, &
blocklengths(4)=(/1,1,1,1/), &
types(4)=(/MPI_LB,mpi_double_precision, &
mpi_integer,MPI_UB/)
integer(kind=mpi_address_kind) :: displs(4)
type(bartype) :: bararray(4)
integer :: rank, ierr, i, test(4)
call mpi_init(ierr)
call mpi_comm_rank(mpi_comm_world, rank, ierr)
call mpi_get_address(bararray(1), displs(1))
call mpi_get_address(bararray(1)%x, displs(2))
call mpi_get_address(bararray(1)%i, displs(3))
call mpi_get_address(bararray(2), displs(4))
do i=4,1,-1
displs(i)=displs(i)-displs(1)
enddo
call mpi_type_create_struct(4,blocklengths,displs,types,mpi_bar_type,ierr)
call mpi_type_commit(mpi_bar_type,ierr)
bararray(:)%x=rank
bararray(:)%i=rank
test(:)=rank
print *, "before", bararray
call mpi_bcast(test, 4, mpi_integer, 0, mpi_comm_world,ierr)
call mpi_bcast(bararray, 4, mpi_bar_type, 0, mpi_comm_world,ierr)
print *, "after", bararray
call mpi_finalize(ierr)
end program foo
请注意使用MPI_LB
和MPI_UB
作为结构的其他虚构成员。这是为了确保类型的范围是正确的。
我不完全确定这是按照标准这样做的推荐方法,但它一直对我有用。
据我所知,标准说要在类型定义中添加bind(C)
和sequence
,但即使如此,我也不确定是否设置类型的上限会起作用,因为你会我怀疑有对齐问题。
编辑:在关于MPI_LB和MPI_UB的各种评论确实已经弃用之后,仔细重新阅读标准,我想以下工作并且应该是合规的。
program foo
implicit none
include 'mpif.h'
type bartype
real(8) :: x
integer :: i
end type bartype
integer :: tmp_type, bar_type
integer :: &
count=4, &
blocklengths(2)=(/1,1/), &
types(2)=(/mpi_double_precision, &
mpi_integer/)
integer(kind=mpi_address_kind) :: displs(2), lb, extent
type(bartype) :: bararray(4)
integer :: rank, ierr, i, test(4)
call mpi_init(ierr)
call mpi_comm_rank(mpi_comm_world, rank, ierr)
call mpi_get_address(bararray(1)%x, displs(1))
call mpi_get_address(bararray(1)%i, displs(2))
call mpi_get_address(bararray(1), lb)
call mpi_get_address(bararray(2), extent)
do i=1,2
displs(i)=displs(i)-lb
enddo
extent=extent-lb
lb=0
call mpi_type_create_struct(2,blocklengths,displs,types,tmp_type,ierr)
call mpi_type_commit(tmp_type,ierr)
call mpi_type_create_resized(tmp_type,lb,extent,bar_type,ierr)
call mpi_type_free(tmp_type,ierr)
call mpi_type_commit(bar_type,ierr)
bararray(:)%x=rank
bararray(:)%i=rank
test(:)=rank
print *, "before", bararray
call mpi_bcast(test, 4, mpi_integer, 0, mpi_comm_world,ierr)
call mpi_bcast(bararray, 4, bar_type, 0, mpi_comm_world,ierr)
print *, "after", bararray
call mpi_type_free(bar_type,ierr)
call mpi_finalize(ierr)
end program foo