簡體   English   中英

減去兩個元素(來自相同結構)的地址?

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

我正在編寫程序,並且需要計算結構元素的兩個地址之間的差。 抱歉,如果不清楚,某些代碼可能會更明確。

代碼中有一些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是“包含任何有效地址的C類型”(摘自文檔)。 我在這里嘗試做的事情是計算struc1-> 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將用戶定義的結構的內容寫入文件中。 這就是為什么。

我認為您的推理有些錯誤,即使您給出向量實際位置的地址,也可能將向量的實際元素放置在其他位置。

嘗試例如

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數組的結構?

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

那么您在做什么會更有意義。

嘗試這個:

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

便攜式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表示該緩沖器地址是進程的地址空間的底部)。 這僅適用於發送結構類型的一個實例,因此該類型在send調用之后立即被銷毀。 原則上,為每個要發送的結構實例創建新的數據類型不是什么大問題,因為發送數據的操作要比類型創建和銷毀要昂貴得多。

這就是我用的。 它適用於我的項目,但我不知道為什么兩個解決方案都起作用,因為我認為它們的含義不同:

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 ?

有人可以確認這不是我的情況所獨有的,並且這些方法並非完全陌生/不好嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM