简体   繁体   English

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

[英]Subtract two elements' (from the same structure) addresses?

I am writing a program and I need to calculate the difference between two addresses of a structure's elements. 我正在编写程序,并且需要计算结构元素的两个地址之间的差。 Sorry if it's not clear, some code might be more explicit. 抱歉,如果不清楚,某些代码可能会更明确。

There are some MPI elements in the code but it's not what my problem's about. 代码中有一些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);

  (...)
}

The problem takes place at these lines : 问题发生在以下几行:

MPI_Aint disp[2];
disp[0] = &struc1->itab - &struc1;
disp[1] = &struc1->ctab - &struc1;

First of all, MPI_Aint is a "C type that holds any valid address" (taken from the documentation). 首先,MPI_Aint是“包含任何有效地址的C类型”(摘自文档)。 What I'm trying to do here, it calculate the difference between struc1->itab and struc1 addresses. 我在这里尝试做的事情是计算struc1-> itab和struc1地址之间的差。

Here are the errors I'm getting : 这是我遇到的错误:

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-’

I guess I'm not correctly accessing the addresses, since the types involved here are std::vector<int>* and s_str** . 我猜我没有正确访问地址,因为这里涉及的类型是std::vector<int>*s_str** What's the proper way ? 正确的方法是什么?

More details : I need this to write in a file using MPI-I/O. 更多详细信息:我需要使用MPI-I / O将其写入文件。 It's to tell MPI how many space each proc will need to write its whole dataset. 告诉MPI每个proc需要多少空间来写入其整个数据集。 So basically, I just want to write the content of a user-defined struct in a file, using MPI-I/O. 因此,基本上,我只想使用MPI-I / O将用户定义的结构的内容写入文件中。 Here's why. 这就是为什么。

I think your reasoning is a bit wrong, even if you give the address of where the vectors are the actual elements of the vector may be placed elsewhere. 我认为您的推理有些错误,即使您给出向量实际位置的地址,也可能将向量的实际元素放置在其他位置。

try for instance eg 尝试例如

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

maybe you had originally a struct that had two normal c-arrays? 也许您最初有一个具有两个正常c数组的结构?

typedef struct 
{
  int itab[100];
  char ctab[100];
} struc1;

then it would make more sense what you are doing. 那么您在做什么会更有意义。

try this: 尝试这个:

 disp[0] = ((char *) &(struc1->itab)) - ((char *) struc1);
 disp[1] = ((char *) &(struc1->ctab)) - ((char *) struc1);

The portable MPI way would be: 便携式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;

Anyway, this won't work because std::vector allocates memory for its elements on the heap. 无论如何,这将不起作用,因为std::vector在堆上为其元素分配了内存。 As heap allocations might end up in completely random locations in the process' address space, one should use a slightly different approach: 由于堆分配可能最终会出现在进程地址空间中的完全随机位置,因此应该使用稍微不同的方法:

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);

The structure type is constructed using absolute addresses and therefore MPI_BOTTOM must be used in the MPI_Send call ( MPI_BOTTOM signifies that the buffer address is the bottom of the process' address space). 该结构类型是使用绝对地址构造和因此MPI_BOTTOM必须在使用MPI_Send呼叫( MPI_BOTTOM表示该缓冲器地址是进程的地址空间的底部)。 This only works for sending one instance of the structure type, therefore the type is destroyed immediately after the send call. 这仅适用于发送结构类型的一个实例,因此该类型在send调用之后立即被销毁。 In principle, creating a new datatype for each structure instance to be sent is not a big problem since sending data is much more expensive operation than type creation and destruction. 原则上,为每个要发送的结构实例创建新的数据类型不是什么大问题,因为发送数据的操作要比类型创建和销毁要昂贵得多。

This is what I used. 这就是我用的。 It works on my project, I don't know why both the solutions work though, since I don't think they have the same meaning : 它适用于我的项目,但我不知道为什么两个解决方案都起作用,因为我认为它们的含义不同:

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 ?

Could someone confirm that this is not specific to my case and that those methods are not completely strange/bad? 有人可以确认这不是我的情况所独有的,并且这些方法并非完全陌生/不好吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM