我正在编写程序,我需要计算结构元素的两个地址之间的差异。对不起,如果不清楚,某些代码可能更明确。
代码中有一些MPI元素,但这不是我的问题所在。
typedef struct Str {
std::vector<int> itab;
std::vector<char> ctab;
} s_str;
int main(int argc, char **argv)
{
s_str *struc1 = new s_str();
MPI_Datatype Strtype;
int count = 2;
int lengths[2] = { 8, 8 };
MPI_Aint disp[2];
disp[0] = &struc1->itab - &struc1;
disp[1] = &struc1->ctab - &struc1;
MPI_Datatype types[2] = { MPI_INT, MPI_CHAR };
MPI_Type_create_struct(count, lengths, disp, types, &Strtype);
MPI_Type_commit(&Strtype);
(...)
}
问题发生在以下几个方面:
MPI_Aint disp[2];
disp[0] = &struc1->itab - &struc1;
disp[1] = &struc1->ctab - &struc1;
首先,MPI_Aint是一个&#34; C类型,它包含任何有效的地址&#34; (取自文件)。我在这里尝试做的是计算struc1-&gt; itab和struc1地址之间的差异。
以下是我遇到的错误:
tmp2.cpp: In function ‘int main(int, char**)’:
tmp2.cpp:30:30: erreur: invalid operands of types ‘std::vector<int>*’ and ‘s_str** {aka Str**}’ to binary ‘operator-’
tmp2.cpp:31:30: erreur: invalid operands of types ‘std::vector<char>*’ and ‘s_str** {aka Str**}’ to binary ‘operator-’
我想我没有正确访问这些地址,因为此处涉及的类型是std::vector<int>*
和s_str**
。什么是正确的方法?
更多细节:我需要使用MPI-I / O写入文件。告诉MPI每个proc需要多少空间来编写整个数据集。基本上,我只想使用MPI-I / O在文件中编写用户定义结构的内容。这就是原因。
答案 0 :(得分:1)
我认为你的推理有点不对,即使你给出了向量的地址,向量的实际元素也可以放在其他地方。
尝试例如。
s_str struc1;
struc1.itab.push_back(0);
printf( "struc1.itab %p\n", (void*)&(struc1.itab) );
printf( "struc1.ctab %p\n", (void*)&(struc1.ctab) );
printf( "struc1.itab[0] %p\n", (void*)&(struc1.itab[0]) );
printf( "struc1 %p\n", (void*)&struc1 );
struc1.itab 000000000022fde0
struc1.ctab 000000000022fdf8
struc1.itab[0] 0000000000327f40
struc1 000000000022fde0
也许你最初的结构有两个普通的c-array?
typedef struct
{
int itab[100];
char ctab[100];
} struc1;
那么你会更有意义。
答案 1 :(得分:0)
试试这个:
disp[0] = ((char *) &(struc1->itab)) - ((char *) struc1);
disp[1] = ((char *) &(struc1->ctab)) - ((char *) struc1);
答案 2 :(得分:0)
便携式MPI方式是:
MPI_Aint base;
MPI_Get_address(&struc1, &base);
MPI_Get_address(&struc1->itab, &disp[0]);
disp[0] -= base;
MPI_Get_address(&struc1->ctab, &disp[1]);
disp[1] -= base;
无论如何,这不起作用,因为std::vector
为堆上的元素分配内存。由于堆分配可能最终位于进程地址空间中的完全随机位置,因此应该使用稍微不同的方法:
MPI_Aint disp[2];
// N.B. both displacements are ABSOLUTE addresses
MPI_Get_address(&struc1->itab[0], &disp[0]);
MPI_Get_address(&struc1->ctab[0], &disp[1]);
MPI_Type_create_struct(count, lengths, disp, types, &Strtype);
MPI_Type_commit(&Strtype);
MPI_Send(MPI_BOTTOM, 1, Strtype, ...);
MPI_Type_free(&Strtype);
结构类型是使用绝对地址构造的,因此必须在MPI_BOTTOM
调用中使用MPI_Send
(MPI_BOTTOM
表示缓冲区地址是进程'地址空间的底部) 。这仅适用于发送结构类型的一个实例,因此在发送调用后立即销毁该类型。原则上,为每个要发送的结构实例创建一个新的数据类型并不是一个大问题,因为发送数据比创建和销毁类型的操作要昂贵得多。
答案 3 :(得分:0)
这就是我用的。它适用于我的项目,我不知道为什么这两个解决方案都有效,因为我认为它们没有相同的含义:
MPI_Aint disp[2] = { 0, (uintptr_t)&(struc1->ctab[0]) - (uintptr_t)&(struc1->itab[0]) };
MPI_Aint disp[2] = { 0, sizeof (std::vector<int>) + sizeof (std::vector<char>) };
// Why do both of these solutions work ?
有人可以确认这不是特定于我的情况而且那些方法并不完全奇怪/不好吗?