2015-09-14 21 views
3

我正在學習MPI編程並編寫了以下程序。它添加一整行數組並輸出總和。在等級0(或過程0)中,它將調用其所有從屬隊列來進行計算。我只想使用其他兩個從屬隊列/進程來完成此操作。每當我嘗試調用相同的等級兩次,如下面的代碼所示,我的代碼只會掛在中間,不會執行。如果我不叫同級別的兩倍,代碼將使用時正常工作如何使用C語言在MPI中調用相同的等級?

#include "mpi.h" 
#include <stdio.h> 
#include <stdlib.h> 

int main (int argc, char *argv[]) 
{ 
     MPI_Init(&argc, &argv); 
     int world_rank; 
     MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
     int world_size; 
     MPI_Comm_size(MPI_COMM_WORLD, &world_size); 
     int tag2 = 1;  
     int arr[30] = {0}; 

     MPI_Request request; 
     MPI_Status status; 

     printf ("\n--Current Rank: %d\n", world_rank); 
     int index; 
     int source = 0; 
     int dest; 
     if (world_rank == 0) 
     { 
      int i; 

      printf("* Rank 0 excecuting\n"); 
      index = 0; 
      dest = 1; 
      for (i = 0; i < 30; i++) 
      { 
       arr[ i ] = i + 1; 
      }   
      MPI_Send(&arr[0], 30, MPI_INT, dest, tag2, MPI_COMM_WORLD); 

      index = 0; 
      dest = 2; 
      for (i = 0; i < 30; i++) 
      { 
       arr[ i ] = 0; 
      } 
      MPI_Send(&arr[0], 30, MPI_INT, dest, tag2, MPI_COMM_WORLD);   

      index = 0; 
      dest = 2; //Problem happens here when I try to call the same destination(or rank 2) twice 
      //If I change this dest value to 3 and run using: mpirun -np 4 test, this code will work correctly 
      for (i = 0; i < 30; i++) 
      { 
       arr[ i ] = 1; 
      } 
      MPI_Send(&arr[0], 30, MPI_INT, dest, tag2, MPI_COMM_WORLD); 
     } 
     else 
     { 
      int sum = 0; 
      int i; 
      MPI_Irecv(&arr[0], 30, MPI_INT, source, tag2, MPI_COMM_WORLD, &request); 
      MPI_Wait (&request, &status); 
      for(i = 0; i<30; i++) 
      { 
       sum = arr[i]+sum; 
      } 
      printf("\nSum is: %d at rank: %d\n", sum, world_rank); 
     }  

     MPI_Finalize(); 
} 

結果:-np的mpirun 3測試

--Current Rank: 2 

Sum is: 0 at rank: 2 

--Current Rank: 0 
* Rank 0 excecuting 

--Current Rank: 1 

Sum is: 524800 at rank: 1 
        //Program hangs here and wouldn't show sum of 30 

請讓我知道我可以調用同排名兩次。例如,如果我只有另外兩個可以調用的從屬進程。 請如果可能的話

回答

4

在MPI,每個進程執行相同的代碼的例子表明,正如你在做什麼,你主要是通過if/else語句檢查等級區分不同的進程。主級別爲0的進程正在進行3次發送:發送到進程1,然後發送到進程2.每個從進程只做一次接收,這意味着等級1接收到它的第一條消息,等級2接收到它的第一條消息。當您在進程0上調用第三個MPI_Send時,由於從站已完成其他塊的執行,因此在該點之後沒有且將不會有任何等待接收消息的從站。當主人等待發送最終消息時,程序被阻止。

爲了解決這個問題,你必須確保等級2的奴隸執行兩個接收,或者只爲該過程添加一個循環,或者只爲該過程重複(因此,使用if(world_rank == 2)檢查)該塊代碼

 sum = 0; //resetting sum 
     MPI_Irecv(&arr[0], 1024, MPI_INT, source, tag2, MPI_COMM_WORLD, &request); 
     MPI_Wait (&request, &status); 
     for(i = 0; i<1024; i++) 
     { 
      sum = arr[i]+sum; 
     } 
     printf("\nSum is: %d at rank: %d\n", sum, world_rank); 
1

TL; DR:只是一句話是主/從的做法是不被看好,可能會持久格式化程序員的心態,導致可憐的代碼投入生產時


儘管克拉麗莎是完全正確的,她的回答非常明確,但我想補充一些一般性評論,不是關於代碼本身,而是關於並行計算原理和良好習慣。首先一個快速的序言:當人們想要平行化代碼時,可能有兩個主要原因:使其更快和/或允許它通過克服一個單獨發現的限制(如內存限制)來處理更大的問題機。但是在所有情況下,性能都很重要,我總是會認爲MPI(或者說通常是平行的)程序員對性能感興趣並且擔心。所以我的文章的其餘部分會假設你是。

現在這篇文章的主要原因是:在過去的幾天裏,我在這裏看到了關於MPI和並行化的幾個問題,顯然來自渴望學習MPI(或者OpenMP)的人。這很棒!並行編程很棒,並且沒有足夠的並行程序員。所以我很高興(我敢肯定,很多SO成員也是)回答幫助人們學習如何並行編程的問題。在學習如何並行編程的背景下,你必須編寫一些簡單的代碼,做簡單的事情,以便了解API的功能和工作原理。這些程序可能從遠處看起來很愚蠢,而且效果很差,但沒關係,這就是傾斜如何工作。大家都是這樣學習的。

但是,您必須記住,您編寫的這些程序只是:API學習練習。它們不是真實的東西,也不反映真正的並行程序是什麼或應該是什麼的哲學。我在這裏的答案是我在這裏看到的,在其他問題和答案中反覆提出了「主」過程和「奴隸」過程的地位。這是錯誤的,根本錯誤!讓我解釋一下爲什麼:

由於Clarissa完美地指出了,「在MPI中,每個進程執行相同的代碼」。我們的想法是找到一種方法來製作幾個進程進行交互以共同解決(可能更大)的問題(希望更快)。但在這些過程中,沒有任何特殊的地位,它們都是平等的。他們有一個ID可以解決它們,但0級不比1級或1025級更好......通過人爲地決定#0過程是「主」而其他過程是它的「奴隸」,你會中斷這種對稱性和它的後果:

現在,#0的排名是主,它的命令,對吧?這是主人所做的。因此,它將獲得運行代碼所需的信息,將其分發給工作人員,並指示他們進行處理。然後它會等待處理結束(可能會讓自己處於繁忙狀態,但更有可能只是等待或戳動工人,因爲這是主人的工作),收集結果,做一些重新組合並輸出。任務完成!那有什麼問題?

好了,下面是錯誤的:

  1. 在主獲取數據的時間,從站閒置。這是連續的和無效的處理...
  2. 然後數據和工作的分配意味着大量的轉移。這需要時間,並且由於它僅在進程#0和所有其他進程之間,這可能會在單個鏈路上在網絡上產生大量擁塞。
  3. 雖然工人在做他們的工作,但主人應該做什麼?還能工作嗎?如果是,那麼它可能不容易處理來自從站的請求,延遲整個並行處理。等待這些請求?然後,它閒置時浪費了大量的計算能力......最終,沒有好的答案。
  4. 然後以相反的順序重複點1和2,並收集結果和輸出或結果。這是很多數據傳輸和順序處理,這將嚴重破壞全球可擴展性,有效性和性能。

所以,我希望你現在明白爲什麼主/從方法是(通常並不總是,但經常)是錯誤的。我從過去幾天所讀到的問題和答案中看到的危險是,你可能會讓你的思維格式化爲這種方法,就好像它是平行思維的「正常」方式。那麼,它不是!並行編程是對稱的。它在全球各地同時處理這個問題。您必須從一開始就平行思考,並將您的代碼視爲全局並行實體,而不僅僅是需要指導如何操作的一系列流程。每個過程都是自己的主人,在平等的基礎上與同伴打交道。每個進程應儘可能自行獲取其數據(並行處理);根據處理中涉及的對等點的數量及其ID確定要做什麼;必要時與同行交換信息,如果是本地(點對點通信)或全球(集體通信);併發布其自己的份額的結果(再次導致並行處理)...

好吧,這對於剛開始學習並行編程的人來說有點極端的要求,我不想告訴你,你的學習練習應該是這樣的。但請牢記目標,不要忘記API學習示例只是API學習示例,而不是簡化的實際代碼模型。因此,不斷嘗試MPI電話以瞭解他們的工作方式以及他們的工作方式,但要儘量慢慢傾向於採用對稱方式處理您的示例。這隻會對你長遠有益。

對不起,這個冗長且有點離題的答案,祝你的並行編程好運。

+0

'tl; dr'我沒有,快速瀏覽一下,發現你的'答案'中有任何不同意見。讓我感到困擾的是,你可能已經發布了它針對你提到的那些最近的初學者-MPI問題(或者這裏的許多其他問題),這表明它不是這個問題的好答案。我懷疑這可能是http://programmers.stackexchange.com上的一個問題的一個很好的答案,但我不知道是否曾經有人問過這個問題。 –

+0

@HighPerformanceMark你是對的,我可以做出這個答案,這更像是你對這些初學者的問題的評論/建議,如你注意到的答案。那麼爲什麼這個問題而不是其他問題呢?也許只是爲了讓它在這裏準備好並在將來需要時提及它......這似乎與SO的使用策略相符合嗎? – Gilles

+0

我不確定我知道SO的使用政策是什麼 - 除了讓社區決定。這是有用的信息和建議,至少與問題相關,這兩方面都使得它在這裏的答案的50%以上。我當然不會投下它,事實上,該死的,我要去投票... –