![](/img/trans.png)
[英]Are the addresses of two temporaries guaranteed to be different in the same expression?
[英]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.