Fortran90派生类型与mpi,对齐问题? [英] Fortran90 derived types with mpi, alignment issue?

查看:281
本文介绍了Fortran90派生类型与mpi,对齐问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了以下基本代码的问题:

 程序foo 

使用mpi

隐含无

类型bartype
real(8):: x
整数:: i
结束类型bartype

integer :: mpi_bar_type

integer ::&
count = 2,&
blocklengths(2)=(/ 1,1 /),&
类型(2)=(/ mpi_double_precision,&
mpi_integer /)
整数(kind = mpi_address_kind):: displs(2)
类型(bartype):: bar, bararray(4)
integer :: rank,ierr,i,test(4),addr0


call mpi_init(ierr)
call mpi_comm_rank(mpi_comm_world,rank ,ierr)

调用mpi_get_address(bar,addr0)
调用mpi_get_address(bar%x,displs(1))
调用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)
调用mpi_type_commit(mpi_bar_type,ierr)

bararray(:)%x =等级
bararray(:)%i =等级
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)

结束程序foo

我在派生类型Bcast(使用intelMPI和openMPI),在调试器(DDT)中,据说这可能是一个对齐问题...



我已经看到<一个href =https://stackoverflow.com/questions/24275497/derived-data-types-with-mpi>这个线程,问题似乎是相同的,但我仍然没有解决方案...

感谢您的帮助!

解决方案

试试这个:

 程序foo 
隐含无
包含'mpif.h'

类型bartype
real(8):: x
整数:: i
结束类型bartype

整数:: mpi_bar_type

整数::&
count = 4,&
blocklengths(4)=(/ 1,1,1,1 /),&
类型(4)=(/ MPI_LB,mpi_double_precision,&
mpi_integer,MPI_UB /)
整数(kind = mpi_address_kind):: displs(4)
类型(bartype) :: bararray(4)
integer :: rank,ierr,i,test(4)


调用mpi_init(ierr)
调用mpi_comm_rank(mpi_comm_world,rank ,ierr)

调用mpi_get_address(bararray(1),displs(1))
调用mpi_get_address(bararray(1)%x,displs(2))
调用mpi_get_address bararray(1)%i,displs(3))
call mpi_get_address(bararray(2),displs(4))

do i = 4,1,-1
(1)
enddo

调用mpi_type_create_struct ,ierr)

bararray(:)%x =等级
bararray(:)%i =等级
test(:)=等级
print *,之前,bararray

call mpi_bcast(test,4,mpi_integer,0,mpi_comm_world,ierr)
call mpi_bcast(bararray,4,mpi_bar_type,0,mpi_com m_world,ierr)

print *,after,bararray

调用mpi_finalize(ierr)

结束程序foo

注意使用 MPI_LB MPI_UB 作为该结构的额外虚构成员。这是为了确保类型的范围是正确的。
我不完全相信这是根据标准推荐的方法,但它一直适用于我。
据我所知,该标准规定为您的 bind(C)和一个序列添加一个类型定义,但即使如此,我不确定没有设置该类型的上限会起作用,因为您将有我怀疑的对齐问题。






编辑:在对MPI_LB和MPI_UB进行各种评论后,确实不赞成使用,并仔细重新阅读标准,我想下面的工作应该符合标准。 / p>

 程序foo 
隐式无
包含'mpif.h'

类型bartype
real(8):: x
integer :: i
结束类型bartype

整数:: tmp_type,bar_type

整数::&
count = 4,&
blocklengths(2)=(/ 1,1 /),&
类型(2)=(/ mpi_double_precision,&
mpi_integer /)
整数(kind = mpi_address_kind):: displs(2),lb,范围
类型(bartype) :: bararray(4)
integer :: rank,ierr,i,test(4)


调用mpi_init(ierr)
调用mpi_comm_rank(mpi_comm_world,rank ,ierr)

调用mpi_get_address(bararray(1)%x,displs(1))
调用mpi_get_address(bararray(1)%i,displs(2))
call mpi_get_address(bararray(1),lb)
调用mpi_get_address(bararray(2),extent)

do i = 1,2
displs(i)= displs(i) -bb
enddo
extent = extent-lb
lb = 0

调用mpi_type_create_struct(2,blocklengths,displs,types,tmp_type,ierr)
调用mpi_type_commit(tmp_type,ierr)
调用mpi_type_create_resized(tmp_type,lb,extent,bar_type,ierr)
调用mpi_type_free(tmp_type,ierr)
调用mpi_type_commit(bar_type,ierr)

bararray(:)%x =等级
bararray(:)%i =等级
测试(:)=等级
p rint *,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

调用mpi_type_free(bar_type,ierr)
调用mpi_finalize(ierr)

结束程序foo


I got problem with the following basic code:

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

I get a segfault at the derived type Bcast (with intelMPI and openMPI), an in a debugger (DDT), it is said that this might be an alignment problem...

I already saw this thread, where the problem seems to be the same, but I have still got no solution...

Thanks for helping!

解决方案

Just try 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

Note the use of MPI_LB and MPI_UB as additional fictitious members of the structure. This is to ensure that the extents of the type is right. I'm not entirely sure this is the recommended way for doing that according to the standard, but it has always worked for me. For what I know, the standard says to add a bind(C) and a sequence to your type definition, but even though, I'm not sure not setting the upper bound of the type would work since you will have alignment issue I suspect.


EDIT: after the various remarks about MPI_LB and MPI_UB which are indeed deprecated, and a careful re-reading of the standard, I guess the following works and should be compliant.

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

这篇关于Fortran90派生类型与mpi,对齐问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆