减去两个元素(来自相同结构)的地址?

时间:2014-10-09 09:16:51

标签: c++ struct mpi

我正在编写程序,我需要计算结构元素的两个地址之间的差异。对不起,如果不清楚,某些代码可能更明确。

代码中有一些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在文件中编写用户定义结构的内容。这就是原因。

4 个答案:

答案 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_SendMPI_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 ?

有人可以确认这不是特定于我的情况而且那些方法并不完全奇怪/不好吗?