Fortran90 派生类型与 mpi,对齐问题?
Fortran90 derived types with mpi, alignment issue?
我在使用以下基本代码时遇到问题:
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
我在调试器 (DDT) 的派生类型 Bcast(使用 intelMPI 和 openMPI)处遇到段错误,据说这可能是对齐问题...
我已经看过this个帖子,问题似乎是一样的,但我仍然没有解决方案...
感谢您的帮助!
试试这个:
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
我在使用以下基本代码时遇到问题:
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
我在调试器 (DDT) 的派生类型 Bcast(使用 intelMPI 和 openMPI)处遇到段错误,据说这可能是对齐问题...
我已经看过this个帖子,问题似乎是一样的,但我仍然没有解决方案...
感谢您的帮助!
试试这个:
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