mpi並行中定義的變數每個cpu中都有嗎?
1. 程序採用mpi並行,那麼程序中定義的變數在每個cpu中都有一個同名變數嗎?如果是,那mpi_bcast and mpi_send 還有什麼意義呢?
2. 程序中的代碼,如果不指明用哪個cpu執行的話,是每個cpu均執行一遍嗎?剛剛接觸,有些不明白,忘見諒。
1. MPICH的基本想法其實是這樣的,它把一份代碼複製多份,然後各自生成「子程序」各自運行。因此,代碼中的每個變數存在於每個每個進程中。然後通過各個「子程序」之間進行通訊等,比如MPI_SEND來實現某些變數的「共享」,通過mpi_barrier等來控制各個「子程序」的進度等。2. 我好像沒見過MPICH裡面有指定具體執行CPU的函數。一般來說,我們只指定進程數,就是上面說的「子程序」的個數。而各個進程怎麼運行,則完全是計算機自動調度的。如果計算機允許的最大進程數大於等於指定進程數,而且計算機沒有其它繁重任務時候,一般會把我們的程序分開到各個核運行,這樣的效率是比較高的。否則,可能會出現多個進程在一個核運行的問題,會增加CPU的調度時間,執行效果變差
先簡單說說MPI的編程方式:
MPI的模型叫做SPMD,single program multiple data。意思就是運行同一個程序,但是處理不同的數據。實現上,每一個mpi進程都是一個獨立的程序,相互之間通過MPI communicator通信交換數據,他們之間通過rank編號來區分。如果沒有使用rank編號區分的話,那麼確實,這個變數是每個進程裡面都一樣的。但是實際中的大部分數據,都會根據進程編號而不同。
比如一個for(int i = 0; i &< 100; i++) calc(data[i]); 分成nprocs=4個進程。一般的做法是生成要處理的數組,可以用if(rank == 0){}語句塊,在rank=0進程生成[0,100),然後把data[rank*25]到data[(rank+1)*25]發送到編號為rank的進程,然後每個進程執行for(int i = 0; i &< 25; i++) calc(data[i])即可。
這個例子裡面,有相同的變數,比如 i,都是0-25,也有不同的數據,比如每個進程得到的data[25]數組,內容是不同的。SPMD裡面的data,含義指的就是這個data數組。它作為處理對象在不同的進程裡面必然是不同的,其他的變數就不一定了。
也有些做法是直接每個進程各自根據rank自己生成或者讀取需要處理的數據的,就不需要發送那一步了。
你的問題:1. 廣播到world的變數,確實各個進程裡面都是一樣的,但是send的變數,一般是跟我剛才所說,每個不同rank的進程只會收到數組裡面的一塊,處理的數據也就不同。所以沒有寫錯的MPI程序,是不應該每個進程都處理一樣的數據的,那樣的重複勞動毫無意義。2. MPI的代碼都是指定進程編號執行,不是指定CPU。綁定CPU是mpirun參數的工作,不是MPI程序自己的工作。一般的做法一個就是if(rank == 0)這種語句塊,來讓不同的進程執行不同的指令,一般用於在rank 0主進程裡面做一些不耗時的工作。至於耗時的工作,一個個用這種if語句塊在每個進程裡面執行那會很要命,因為進程可能會很多。一般的做法就是我剛才那個例子,各自存儲不同的數據,運行同樣的cpu指令來算。後面這個做法更貼近SPMD的含義,運行一樣的程序塊,處理不同的數據。
mpi的架構是這樣子的,mpirun起的進程都有同名變數(另外指定的不算)。然後在每個進程里可以拿到自己的進程id號。這時就可以通過mpi_send,mpi_recv這類指令從某個進程發送某個變數到另外一個進程。對於最新版本的mpi,mpi在起進程的時候可以決定哪個進程起在哪個核上。順序,隨機,甚至指定核的號碼。這樣子做有好處,可以幫助某些進程共享cache,做一些頻繁通信。剛才說了另外指定的不算的情況是指,比如進程拿到了tid這個自己的進程id號。那麼if (tid==1) {..}這個大括弧裡面的語句只有進程號為1的進程才會執行。其他進程則直接往下走了,除非遇到阻塞操作等在那。
補充一下。
1,mpi針對的是分散式內存系統,在它眼中,一個CPU對應一塊內存,每個CPU只能訪問自己的內存,不能訪問其他CPU的內存。
在程序中聲明變數後,每個CPU都會有一個同名變數,也就是都會在自己的內存中創建同一個名字的空間。但是這些變數在不同的內存中,有不同的地址,他們不是同一個變數,僅僅是重名而已。由於CPU不能訪問別人的內存,所以當它需要其他CPU中的數據時,就要讓那個CPU主動把數據send過去。2,是的。推薦閱讀:
※為什麼知乎上這麼多做計算機科學的?
※你見過最美的程序是什麼?
※為什麼gta里的樹是無敵的,而電線杆是可以撞倒的?是因為技術原因嗎?
※c++中如何為一個程序寫擴展?
※代碼里寫很多if會影響效率嗎?