2012-12-07 54 views
0

我有一個結構:mpi_gather與動態數組結構

typedef struct 
{ 
double distance; 
int* path; 
} tour; 

然後我試圖從所有進程收集的結果:

MPI_Gather(&best, sizeof(tour), MPI_BEST, all_best, sizeof(tour)*proc_count, MPI_BEST, 0, MPI_COMM_WORLD); 

收集我的根之後,會是all_best containts只有1個正常的元素和其他垃圾。 all_best的類型是tour *。 MPI_BEST的

初始化:

void ACO_Build_best(tour *tour,int city_count, MPI_Datatype *mpi_type /*out*/) 
{ 
int block_lengths[2]; 
MPI_Aint displacements[2]; 
MPI_Datatype typelist[2]; 
MPI_Aint start_address; 
MPI_Aint address; 

block_lengths[0] = 1; 
block_lengths[1] = city_count; 

typelist[0] = MPI_DOUBLE; 
typelist[1] = MPI_INT; 

MPI_Address(&(tour->distance), &displacements[0]); 
MPI_Address(&(tour->path), &displacements[1]); 

displacements[1] = displacements[1] - displacements[0]; 
displacements[0] = 0; 

MPI_Type_struct(2, block_lengths, displacements, typelist, mpi_type); 
MPI_Type_commit(mpi_type); 
} 

任何想法都歡迎。

回答

3

除了將不正確的長度傳遞給MPI_Gather,MPI實際上並不遵循指針指針。使用這樣的結構化類型,您將發送值distancepath指針的值(實質上是發送到其他進程時沒有意義的地址)。如果人設想distance基本上給出path元素的數量,那麼你可以種實現自己的目標與MPI_GatherMPI_Gatherv組合:

首先,收集長度:

int counts[proc_count]; 

MPI_Gather(&best->distance, 1, MPI_INT, counts, 1, MPI_INT, 0, MPI_COMM_WORLD); 

現在即counts填充了正確的長度,您可以繼續並使用MPI_Gatherv接收所有路徑:

int disps[proc_count]; 

disps[0] = 0; 
for (int i = 1; i < proc_count; i++) 
    disps[i] = disps[i-1] + counts[i-1]; 
// Allocate space for the concatenation of all paths 
int *all_paths = malloc((disps[proc_count-1] + counts[proc_count-1])*sizeof(int)); 
MPI_Gatherv(best->path, best->distance, MPI_INT, 
      all_paths, counts, disps, MPI_INT, 0, MPI_COMM_WORLD); 

現在,您可以在all_paths中鏈接所有路徑。您可以通過在all_paths的位置disps[i]開始counts[i]元素來檢查或提取單個路徑。或者你甚至可以建立tour結構數組,讓他們使用已分配和填充路徑儲存:

tour *all_best = malloc(proc_count*sizeof(tour)); 
for (int i = 0; i < proc_count; i++) 
{ 
    all_best[i].distance = counts[i]; 
    all_best[i].path = &all_paths[disps[i]]; 
} 

,或者您可以複製,而不是細分:

for (int i = 0; i < proc_count; i++) 
{ 
    all_best[i].distance = counts[i]; 
    all_best[i].path = malloc(counts[i]*sizeof(int)); 
    memcpy(all_best[i].path, &all_paths[disps[i]], counts[i]*sizeof(int)); 
} 
// all_paths is not needed any more and can be safely free()-ed 

編輯:因爲我忽略了tour結構的定義,上面的代碼實際上工作的:

struct 
{ 
    int distance; 
    int *path; 
} 

其中distance保持第e在path中的重要元素的數量。這與您的情況不同,但沒有關於tour.path如何分配(和大小)的信息,很難提供具體的解決方案。

+0

您確定counts [0]和all_paths [0]來自同一個元素嗎? –

+0

@T_T,'MPI_Gather [v]'按進程的順序排列接收到的塊,因此'counts [0]'將總是排序爲'0'的元素的數量,'all_paths [0]'將是來自等級'0'的路徑中的第一項。但是現在我看到「距離」不是整數,所以事情變得更加複雜。你能告訴我如何分配tour.path嗎? –

+0

我已將距離類型更改爲int。你的回答有幫助。謝謝。 –