fortran 如何定义 unsigned short integer
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fortran 如何定义 unsigned short integer相关的知识,希望对你有一定的参考价值。
请教高手,在fortran 里面如何定义unsigned short integer; short integer; unsigned long integer; signed long integer
unsigned short integer; short integer 变量在fortran中对应的定义方法是:integer(kind=2):: a
unsigned long integer; signed long integer变量在fortran中对应的定义方法是:
integer(kind=4):: a
necrohan指出我的回答有误,从某个方面来说,他是对的。
但是,我相信楼主提问的目的是混合编程,比如vc调用fortran,这个时候存在数据传递的问题,也就衍生出定义的对应问题。我要回答是就是这个。上面我给的对应的定义在数据传递时应该不会有问题的。
至于要实现类型的“定义域”相同,这个如necrohan所说,无符号类型在fortran中是做不到的,但是我们可以做到放宽定义,并在编写程序时注意数据范围就行了。 参考技术A 实际上Fortran里没有unsigned short和unsigned long类型数据!!!
fortran里的数据都是有符号的
楼上回答部分是正确的,但是无符号类型数据范围正数部分扩大了,在fortran里只能用更长字节的数据表示,否则可能会出错。
C或C++里short是2字节,long是4字节
fortran里用integer(n)的形式,integer(2)和integer(4)分别表示2字节和4字节,只能对应signed类型数据,不能对应unsigned类型数据。本回答被提问者采纳
使用 MPI 和 Fortran 90 发送自定义类型
【中文标题】使用 MPI 和 Fortran 90 发送自定义类型【英文标题】:Send custom type using MPI and Fortran 90 【发布时间】:2015-01-21 16:15:00 【问题描述】:在我的程序中,我让每个处理器计算一个自定义类型“点”的数组,该数组由 4 个双精度值和 3 个双精度值组成。我现在希望每个处理器将其“点”类型数组发送到主处理器。
我无法理解如何使用 MPI_type 命令发送自定义类型。尤其是“点”类型中的双复精度。据我了解,MPI 没有 MPI_DOUBLE_COMPLEX 类型。
PROGRAM hello
use mpi
IMPLICIT NONE
INTEGER, PARAMETER :: dp = REAL(KIND(0.0D0))
type point
sequence
real(kind=dp) :: x, y, z, w
double complex :: ex, ey, ez
end type point
type(point), dimension(:), allocatable :: my_points
...
if(rank .ne. master) then
call MPI_SEND(my_points, count, [point?], master, 7, MPI_COMM_WORLD, ierror)
end if
....
END
【问题讨论】:
值得注意的是DOUBLE COMPLEX
是一个非标准的供应商扩展,而不是标准的 Fortran。我推荐complex(dp)
。
【参考方案1】:
MPI 标准规定(MPI 2.2 规范中的第 3.2.2 节):
MPI 需要支持这些数据类型,这些数据类型与 Fortran 和 ISO C 的基本数据类型匹配。如果宿主语言具有其他数据类型,则应提供其他 MPI 数据类型: MPI_DOUBLE_COMPLEX 用于声明为 @987654321 类型的 Fortran 中的双精度复数@; ...
至于数据类型的构造,它是这样工作的。首先,声明一个类型为或(只需使用已分配的)的伪二元数组并结合MPI_GET_ADDRESS
获取每个字段的地址:
type(point) :: dummy(2)
integer(kind=MPI_ADDRESS_KIND) :: offsets(7)
integer :: ierr
call MPI_GET_ADDRESS(dummy(1)%x, offsets(1), ierr)
call MPI_GET_ADDRESS(dummy(1)%y, offsets(2), ierr)
call MPI_GET_ADDRESS(dummy(1)%z, offsets(3), ierr)
call MPI_GET_ADDRESS(dummy(1)%w, offsets(4), ierr)
call MPI_GET_ADDRESS(dummy(1)%ex, offsets(5), ierr)
call MPI_GET_ADDRESS(dummy(1)%ey, offsets(6), ierr)
call MPI_GET_ADDRESS(dummy(1)%ez, offsets(7), ierr)
offsets
现在包含绝对地址,因此将它们转换为相对于dummy%x
的偏移量:
integer :: i
do i = 2,7
offsets(i) = offsets(i) - offsets(1)
end do
! dummy%x serves as base address, therefore set the offset to 0
offsets(1) = 0
下一步是自己构造 MPI 数据类型:
integer :: oldtypes(7), lengths(7)
integer :: point_type0
! dummy%x
oldtypes(1) = MPI_DOUBLE_PRECISION
lengths(1) = 1
! dummy%y
oldtypes(2) = MPI_DOUBLE_PRECISION
lengths(2) = 1
! dummy%z
oldtypes(3) = MPI_DOUBLE_PRECISION
lengths(3) = 1
! dummy%w
oldtypes(4) = MPI_DOUBLE_PRECISION
lengths(4) = 1
! dummy%ex
oldtypes(5) = MPI_DOUBLE_COMPLEX
lengths(5) = 1
! dummy%ey
oldtypes(6) = MPI_DOUBLE_COMPLEX
lengths(6) = 1
! dummy%ez
oldtypes(7) = MPI_DOUBLE_COMPLEX
lengths(7) = 1
call MPI_TYPE_CREATE_STRUCT(7, lengths, offsets, oldtypes, point_type0, ierr)
(注意:此代码假定real(kind=KIND(0.0D0))
实际上是DOUBLE PRECISION
)
那时你几乎准备好了。 point_type0
可以提交,然后用于发送自定义类型的单个元素,但它可能不适用于数组。原因是编译器可能会在类型的末尾或开头添加填充。 MPI 允许显式设置数据类型的范围。为此,首先确定应该存在的实际范围:
integer(kind=MPI_ADDRESS_KIND) :: extent
! Reuse the offsets array
call MPI_GET_ADDRESS(dummy(1)%x, offsets(1), ierr)
call MPI_GET_ADDRESS(dummy(2)%x, offsets(2), ierr)
extent = offsets(2) - offsets(1)
(这应该清楚为什么需要一个二元素虚拟数组)
现在将点数据类型“调整”到真实范围并提交结果数据类型:
integer :: point_type
call MPI_TYPE_CREATE_RESIZED(point_type0, 0_MPI_ADDRESS_KIND, extent, &
point_type, ierr)
call MPI_TYPE_COMMIT(point_type, ierr)
现在你可以使用新注册的类型了:
if(rank .ne. master) then
call MPI_SEND(my_points(1)%x, count, point_type, &
master, 7, MPI_COMM_WORLD, ierror)
end if
请注意,第一个数组元素的x
字段是明确给出的。这样做是因为在计算偏移量时使用dummy%x
作为基础。
在您的情况下,上述某些步骤可能不是绝对必要的,因为您有一个序列类型,这可能会阻止编译器对齐字段。尽管如此,始终按照所示方式执行它是一个好主意,因为它既适用于打包类型,也适用于非打包类型。如果类型定义中缺少sequence
语句,则允许编译器以它认为合适的任何顺序存储组件。这没有任何改变,因为即使 dummy%x
不是第一个组件,它之前的组件也只会有负偏移。
【讨论】:
不错。real(kind=KIND (0.0D0))
不是按标准保证是DOUBLE PRECISION
吗?
它似乎也可以与call MPI_SEND(my_points, count, point_type, master, 7, MPI_COMM_WORLD, ierror)
和call MPI_RECV(my_points, count, point_type, from, 7, MPI_COMM_WORLD, status, ierror)
一起工作
它可以工作,因为x
是第一个字段,它是一个序列类型。但在一般情况下,如果只给出数组的名称,即如果字段被编译器重新排列,它将不起作用。
@VladimirF,老实说,我对 Fortran 标准的了解非常有限。 MPI 标准规定两者应该是等价的。 MPI 标准中有一些规定可以构建便携式类型,例如MPI_TYPE_CREATE_F90_REAL
,但这在实践中似乎没有得到很好的支持。
很好的答案;我们应该指出类似的问题作为 fortran 中 mpi_type_create_struct 的规范答案。以上是关于fortran 如何定义 unsigned short integer的主要内容,如果未能解决你的问题,请参考以下文章
c++中定义一个buff为unsigned char 型,如何初始化全为0