Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory MPI-MPI类型获取范围和MPI类型获取范围之间的差异_Memory_Fortran_Mpi_Sub Array - Fatal编程技术网

Memory MPI-MPI类型获取范围和MPI类型获取范围之间的差异

Memory MPI-MPI类型获取范围和MPI类型获取范围之间的差异,memory,fortran,mpi,sub-array,Memory,Fortran,Mpi,Sub Array,我在理解mpi\u type\u get\u extent和mpi\u type\u get\u true\u extent之间的区别时遇到了一些问题。实际上,我使用的是前者,期望得到的结果是后者,所以我检查了,我发现(在第4.1.8节数据类型的真实范围) 但是,数据类型范围不能用作 需要分配的空间量,如果用户已修改 范围 这让我认为,只要我没有修改数据类型的范围,我就应该在使用这两个子例程时没有任何区别 但我显然错过了什么 声明了以下MPI派生的数据类型 sizes = [10,10,1

我在理解
mpi\u type\u get\u extent
mpi\u type\u get\u true\u extent
之间的区别时遇到了一些问题。实际上,我使用的是前者,期望得到的结果是后者,所以我检查了,我发现(在第4.1.8节数据类型的真实范围)

但是,数据类型范围不能用作 需要分配的空间量,如果用户已修改 范围

这让我认为,只要我没有修改数据类型的范围,我就应该在使用这两个子例程时没有任何区别

但我显然错过了什么

声明了以下MPI派生的数据类型

sizes    = [10,10,10]
subsizes = [ 3, 3, 3]
starts   = [ 2, 2, 2]
CALL MPI_TYPE_CREATE_SUBARRAY(ndims, sizes, subsizes, starts, MPI_ORDER_FORTRAN, MPI_DOUBLE_PRECISION, newtype, ierr)
下面的代码

call mpi_type_size(newtype, k, ierr)
call mpi_type_get_extent(newtype, lb, extent, ierr)                                                                                             
call mpi_type_get_true_extent(newtype, tlb, textent, ierr)
write(*,*) k/DBS, lb/DBS, extent/DBS, tlb/DBS, textent/DBS ! DBS is the size of double precision
生成输出(显然,所有进程都是相同的)

因此
mpi_type_size
的行为与我预期的一样,返回
产品(补贴)*DBS
in
k
;另一方面,我从
mpi_-type_-get_-extent
mpi_-type_-get_-true_-extent
两个方面都期望只有后者才能返回什么(因为我根本没有修改
newtype
),特别是
222223
,它们基本上是
start(1)+start(2)*大小(1)+start(3)*大小(1)*大小(2)
1+(补贴-1)*[1,尺寸(1),尺寸(1)*尺寸(2)]

为什么
mpi\u type\u获取\u区段
lb
区段中返回
0
产品(尺寸)
,而不考虑
子系统
启动

我没有发布MWE,因为我根本没有错误(不是在编译时,也不是在运行时),我根本不知道前面提到的两个例程的工作方式。基本上,我希望有人能帮助我理解标准文档中对这些子程序的描述,以及为什么得到我没有预料到的结果是正确的

编辑 根据@GillesGouaillardet的要求,我在这个问题的末尾添加了一个“最小”的工作示例,该示例将与至少4个进程一起运行(请与4个进程一起运行,以便获得相同的输出)。最后几行可以取消注释(有意识地),以表明表示非连续内存位置的类型在与
count>1一起使用时可以正常工作,一旦通过
mpi\u type\u create\u resized
正确调整大小后即可正常工作。注释这些行后,程序将为创建的所有类型打印
size
lb
extent
true\u lb
true\u extent
(即使是中间类型,未提交):

所有类型都表示4×4矩阵的一行或一列,因此它们的
大小总是可以预测的
4
;列类型的
extent
true\u extent
也都等于
4
单位,因为它表示内存中的四个连续实数;使用
mpi_type_vector
创建的类型具有
extent
true_extent
都等于
13
reals,如我所料(请参见尼斯草图);如果我想将其与
count>1
一起使用,我必须调整其大小,更改其
范围
(并且
true\u范围
保持不变);现在最困难的部分来了:

使用
mpi\u type\u create\u子数组创建的类型的
范围
是什么?老实说,我本来希望例程返回一个已经调整大小的类型,可以与
count>1
一起使用(即
size=4
extent=1
true\u extent=13
),但它似乎没有:对我来说,
extent
16
,这是全局数组的大小

问题是:为什么?为什么使用
mpi\u type\u create\u subarray
创建的类型的
extent
是大小
array\u参数的元素的乘积


MPI\u Type\u create\u subarray()
创建一个派生数据类型,根据定义,其范围是所有大小的乘积

定义见MPI 3.1标准第96页


MPI\u Type\u create\u subarray()
通常用于MPI-IO,因此扩展数据块的这种定义在这里是有意义的


在这种非常特殊的情况下,它可能不是您所希望的,但请考虑4x4阵列的2x2子阵列。您期望达到什么程度?

(对消失的注释的回答)我没有错误,我只是不理解我对应用于用户定义类型的这两个MPI工具的理解有什么错,例如使用
MPI\u type\u CREATE\u子数组创建的MPI工具
(对于预定义的数据类型,例如
MPI\u DOUBLE\u PRECISION
,没有区别)。您不必回答已删除的注释,毕竟我删除它是有原因的…我的错误意思是不同的结果,但无论如何,我删除了注释。您的代码不可直接编译,但必要的声明是可预测的。关于您的编辑(我重复,我的第一条注释已删除,所以请忘记它),即使是产生要解释的结果的程序通常也需要一个MWE,不仅仅是有错误的程序,还有所有其他程序。无论如何,您的代码可能很好,声明是可预测的,这就是我删除注释的原因。长话短说,
MPI_Type_create_subarray()
可能会修改引擎盖下的范围。在Fortran中,描述二维方阵列的数据类型以
size==extent
结尾,但描述行的数据类型大小相同,但
extent
是一个元素的大小。@GillesGouaillardet,你所说的一个元素的大小是什么意思?就我读过和写过的而言如图所示,Fortran矩阵表示一行
m
类型的
范围是
1+m*(n-1)
,这正是我所期望的
27   0   1000   222   223
 mpi_type_contiguous                    4                    0                    4                    0                    4
 mpi_type_vector                        4                    0                   13                    0                   13
 mpi_type_vector res                    4                    0                    1                    0                   13
 mpi_type_create_subarray               4                    0                   16                    0                   13
 mpi_type_create_subarray res           4                    0                    1                    0                   13
program subarray
use mpi
implicit none
integer :: i, j, k, ierr, myid, npro, rs, mycol, myrowugly, myrow_vec, myrow_sub
integer(kind = mpi_address_kind) :: lb, extent, tlb, textent
real, dimension(:,:), allocatable :: mat
call mpi_init(ierr)
call mpi_comm_rank(mpi_comm_world, myid, ierr)
call mpi_comm_size(mpi_comm_world, npro, ierr)
allocate(mat(npro,npro))
mat = myid*1.0
call mpi_type_size(mpi_real, rs, ierr)

call mpi_type_contiguous(npro, mpi_real, mycol, ierr)
call mpi_type_commit(mycol, ierr)
call mpi_type_size(mycol, k, ierr)
call mpi_type_get_extent(mycol, lb, extent, ierr)
call mpi_type_get_true_extent(mycol, tlb, textent, ierr)
if (myid == 0) print *, 'mpi_type_contiguous         ', k/rs, lb/rs, extent/rs, tlb/rs, textent/rs

call mpi_type_vector(npro, 1, npro, mpi_real, myrowugly, ierr)
call mpi_type_size(myrowugly, k, ierr)
call mpi_type_get_extent(myrowugly, lb, extent, ierr)
call mpi_type_get_true_extent(myrowugly, tlb, textent, ierr)
if (myid == 0) print *, 'mpi_type_vector             ', k/rs, lb/rs, extent/rs, tlb/rs, textent/rs
call mpi_type_create_resized(myrowugly, int(0, mpi_address_kind)*rs, int(1, mpi_address_kind)*rs, myrow_vec, ierr)
call mpi_type_commit(myrow_vec, ierr)
call mpi_type_size(myrow_vec, k, ierr)
call mpi_type_get_extent(myrow_vec, lb, extent, ierr)
call mpi_type_get_true_extent(myrow_vec, tlb, textent, ierr)
if (myid == 0) print *, 'mpi_type_vector res         ', k/rs, lb/rs, extent/rs, tlb/rs, textent/rs

call mpi_type_create_subarray(2, [npro, npro], [1, npro], [0, 0], mpi_order_fortran, mpi_real, myrowugly, ierr)
call mpi_type_size(myrowugly, k, ierr)
call mpi_type_get_extent(myrowugly, lb, extent, ierr)
call mpi_type_get_true_extent(myrowugly, tlb, textent, ierr)
if (myid == 0) print *, 'mpi_type_create_subarray    ', k/rs, lb/rs, extent/rs, tlb/rs, textent/rs

call mpi_type_create_resized(myrowugly, int(0, mpi_address_kind)*rs, int(1, mpi_address_kind)*rs, myrow_sub, ierr)
call mpi_type_commit(myrow_sub, ierr)
call mpi_type_size(myrow_sub, k, ierr)
call mpi_type_get_extent(myrow_sub, lb, extent, ierr)
call mpi_type_get_true_extent(myrow_sub, tlb, textent, ierr)
if (myid == 0) print *, 'mpi_type_create_subarray res', k/rs, lb/rs, extent/rs, tlb/rs, textent/rs

!if (myid == 0) call mpi_send(mat(1,1), 2, mycol, 1, 666, mpi_comm_world, ierr)
!if (myid == 0) call mpi_recv(mat(1,3), 2, mycol, 1, 666, mpi_comm_world, mpi_status_ignore, ierr)
!if (myid == 1) call mpi_recv(mat(1,1), 2, mycol, 0, 666, mpi_comm_world, mpi_status_ignore, ierr)
!if (myid == 1) call mpi_send(mat(1,3), 2, mycol, 0, 666, mpi_comm_world, ierr)
!if (myid == 0) call mpi_send(mat(1,1), 2, myrow_vec, 1, 666, mpi_comm_world, ierr)
!if (myid == 0) call mpi_recv(mat(3,1), 2, myrow_vec, 1, 666, mpi_comm_world, mpi_status_ignore, ierr)
!if (myid == 1) call mpi_recv(mat(1,1), 2, myrow_vec, 0, 666, mpi_comm_world, mpi_status_ignore, ierr)
!if (myid == 1) call mpi_send(mat(3,1), 2, myrow_vec, 0, 666, mpi_comm_world, ierr)
!if (myid == 0) call mpi_send(mat(1,1), 2, myrow_sub, 1, 666, mpi_comm_world, ierr)
!if (myid == 0) call mpi_recv(mat(3,1), 2, myrow_sub, 1, 666, mpi_comm_world, mpi_status_ignore, ierr)
!if (myid == 1) call mpi_recv(mat(1,1), 2, myrow_sub, 0, 666, mpi_comm_world, mpi_status_ignore, ierr)
!if (myid == 1) call mpi_send(mat(3,1), 2, myrow_sub, 0, 666, mpi_comm_world, ierr)
!do i = 0, npro
!if (myid == i) then
!print *, ""
!print *, myid
!do j = 1, npro
!print *, mat(j,:)
!end do
!end if
!call mpi_barrier(mpi_comm_world, ierr)
!end do

call mpi_finalize(ierr)
end program subarray