- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我无法理解 MPI_Type_create_struct 方法。假设我们有一个结构:
struct foo(){
float value;
char rank;
}
我们想将这个结构发送到另一个进程。考虑下面的代码示例:
int count = 2; //number of elements in struct
MPI_Aint offsets[count] = {0, 8};
int blocklengths[count] = {1, 1};
MPI_Datatype types[count] = {MPI_FLOAT, MPI_CHAR};
MPI_Datatype my_mpi_type;
MPI_Type_create_struct(count, blocklengths, offsets, types, &my_mpi_type);
我不确定这个例子中偏移量和 block 长度的作用。有人可以解释一下上面的这两部分吗?
最佳答案
MPI_Type_create_struct()
的目的|如您所知,是提供一种方法来创建用户的 MPI_Datatype
s 映射他的结构化类型。这些新类型随后将可用于 MPI 通信和其他调用,就像默认类型一样,例如允许以与传输 int
数组相同的方式传输结构数组。 s 或 float
现在让我们更详细地了解函数本身。
这是 man
返回的概要命令:
NAME
MPI_Type_create_struct - Create an MPI datatype from a general set of
datatypes, displacements, and block sizes
SYNOPSIS
int MPI_Type_create_struct(int count,
const int array_of_blocklengths[],
const MPI_Aint array_of_displacements[],
const MPI_Datatype array_of_types[],
MPI_Datatype *newtype)
INPUT PARAMETERS
count - number of blocks (integer) --- also number of entries
in arrays array_of_types, array_of_displacements and
array_of_blocklengths
array_of_blocklengths
- number of elements in each block (array of integer)
array_of_displacements
- byte displacement of each block (array of address integer)
array_of_types
- type of elements in each block (array of handles to datatype
objects)
OUTPUT PARAMETERS
newtype - new datatype (handle)
让我们看看输入参数的含义是否需要进一步解释:
count
:这很清楚,在您的情况下,那将是 2
array_of_types
: 嗯,那就是 { MPI_FLOAT, MPI_CHAR }
以你为例array_of_blocklengths
: 再说一遍,不多说了。 { 1, 1 }
这是你需要的array_of_displacements
: 这是你必须更加小心的。它对应于从结构开始到 array_of_types
中列出的每个元素的地址的内存地址偏移量。 .在您的情况下,这类似于 { &f.value - &f, &f.rank - &f }
, 与 f
类型 foo
.这里棘手的部分是,由于潜在的对齐约束,您不能确定这是否等于 { 0, sizeof( float ) }
。 (尽管在这里我很确定它会是)。因此,使用所示的地址偏移量使该方法完全可移植。此外(thx Hristo Iliev 指向我)你可以(并且应该)使用 offsetof()
来自 stddef.h
的宏它为你做这个指针算法,将代码简化为{ offsetof( foo, value ), offsetof( foo, rank ) }
哪个看起来更好。以这种方式初始化参数后,调用 MPI_Type_create_struct()
将返回一个新的 MPI_Datatype
, 这将适合发送或接收一个 foo
当时。原因是这种新类型没有考虑结构的实际范围,包括其字段的对齐约束。你的例子在这方面是完美的,因为它(很可能)是空洞的。
原因是float
s 通常具有 32b 的对齐约束,而 char
没有。因此,第二个结构体的起始地址foo
一系列主题的结尾不在第一个主题的末尾。它位于下一个 32b 对齐的内存地址。这将使我们在结构元素的结尾与数组中下一个元素的开头之间留下 3 个字节的空洞。
要处理此问题,您必须调整类型的大小以使用 MPI_Type_create_resized()
对其进行扩展。 ,内容简介如下:
NAME
MPI_Type_create_resized - Create a datatype with a new lower bound
and extent from an existing datatype
SYNOPSIS
int MPI_Type_create_resized(MPI_Datatype oldtype,
MPI_Aint lb,
MPI_Aint extent,
MPI_Datatype *newtype)
INPUT PARAMETERS
oldtype - input datatype (handle)
lb - new lower bound of datatype (address integer)
extent - new extent of datatype (address integer)
OUTPUT PARAMETERS
newtype - output datatype (handle)
使用起来非常简单 lb
和 extend
可以通过直接调用专门用于此目的的函数来检索,即 MPI_Type_get_extent()
(但实际上,您也可以直接使用 0
和 sizeof( foo )
)。此外,由于用于调用的中介类型 MPI_Type_get_extent()
和 MPI_Type_create_resized()
没有在任何实际的 MPI 通信中使用,它不需要用 MPI_Type_commit()
提交,为您节省一些电话和时间。
现在,您的代码变成了:
int count = 2;
int array_of_blocklengths[] = { 1, 1 };
MPI_Aint array_of_displacements[] = { offsetof( foo, value ),
offsetof( foo, rank ) };
MPI_Datatype array_of_types[] = { MPI_FLOAT, MPI_CHAR };
MPI_Datatype tmp_type, my_mpi_type;
MPI_Aint lb, extent;
MPI_Type_create_struct( count, array_of_blocklengths, array_of_displacements,
array_of_types, &tmp_type );
MPI_Type_get_extent( tmp_type, &lb, &extent );
MPI_Type_create_resized( tmp_type, lb, extent, &my_mpi_type );
MPI_Type_commit( &my_mpi_type );
关于c - 难以理解 MPI_Type_create_struct,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33618937/
我想模拟这个函数: function getMetaData(key) { var deferred = $q.defer(); var s3 = vm.ini
我是一名优秀的程序员,十分优秀!