2013-04-22 88 views
6

我有以下情況:我已經寫了一些簡短的MPI測試代碼,以便找出哪些組合的發送和接收操作在我的代碼中效果最好。C++:奇怪的指針損壞錯誤

該代碼在我自己的計算機上工作得很好(使用8個進程進行測試),但只要我運行一個正在處理的羣集,就會得到一個巨大的錯誤輸出,這是輸出:http://pastebin.com/pXTRSf89

我在我的代碼中做的事情如下:我打電話給我的通信功能100K次,並測量時間。該功能如下所示。我發現,錯誤總是發生在同一次迭代中(大約6K左右)。報告的處理器ID確實會改變。迭代是相同的,即使我使用64個proc而不是8個。問題是:我完全不知道,可能是錯誤的,特別是因爲沒有指針被釋放或分配。

void communicateGrid(int level, real* grid, const Subdomain& subdomain, std::vector<TimeMap>& tm_) { 
    tm_[level]["CommGrid"].start(); 

    MPI_Status status[2]; 
    MPI_Request request[2]; 

    // x 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1) + innerGridpoints_[level][0] - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 0, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1)], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 1, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndexInner(level, 1,1,1) + innerGridpoints_[level][0]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 1, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(&grid[getIndexInner(level, 1,1,1) - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 0, MPI_COMM_WORLD, &status[1]); 

    //y 
    MPI_Isend(&grid[getIndex(level, 0, innerGridpoints_[level][1], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 2, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndex(level, 0, numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 3, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndex(level, 0, innerGridpoints_[level][1] + numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 3, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 2, MPI_COMM_WORLD, &status[1]); 

    // z 
    MPI_Isend(&grid[getIndex(level, 0, 0, innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 4, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level])], 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 5, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level] + innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 5, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 4, MPI_COMM_WORLD, &status[1]); 

    tm_[level]["CommGrid"].stop(); 
} 

mpiTypes_的類型是MPI_Datatype *的全局變量,innerGridpoints_和numOuterGridpoints_是全球性的(我知道這是不是一個好的編碼風格,但我把它僅適用於正時)。 我很確定我的數據類型是正確的,因爲他們在另一個通信功能設置中工作(例如Irecv後面跟着發送)。

Final注意:我只是試圖用一個進程來運行它。然後將下面的出錯:

排名0 [週一年04月22 2時11分23秒2013] [c0-0c1s3n0]致命錯誤 PMPI_Isend:內部MPI錯誤!錯誤堆棧:PMPI_Isend(148): MPI_Isend(buf = 0x2aaaab7b531c,count = 1,dtype = USER,dest = 0, tag = 1,MPI_COMM_WORLD,請求= 0x7fffffffb4d4)失敗(未知)(): 內部MPI錯誤! _pmiu_daemon(SIGCHLD):NID 00070] [c0-0c1s3n0] [週一年04月22二點11分23秒2013] PE RANK 0退出信號中止

再次,這僅發生在羣集上,但製作我的機器。

我很高興能夠檢查任何事情或錯誤可能在哪裏! 謝謝

+0

它工作在哪種品牌的CPU上,哪種品牌的CPU不起作用? – Patashu 2013-04-22 00:29:37

+0

我想知道你的指針是否最終會指向它們不應該有的數據塊。當你做'&grid [getIndex(level,0,0,numOuterGridpoints_ [level] + innerGridpoints_ [level] [2])]''這樣的事情時,是否有機會指向一個不是你自己的塊?或者你所調用的函數中是否有內存泄漏......是兩臺機器上的編譯器/庫的完全相同版本嗎? – Floris 2013-04-22 00:32:39

+0

getIndex和getInnerIndex只是內聯索引函數,因爲網格是3d數組,它們應該沒問題。我的電腦是英特爾i5,使用gcc 4.6.0(Mac系統)進行編譯 - 集羣是帶有Opteron CPU的Cray機器。我嘗試過,但標準的PGI編譯器以及gcc(版本4.6.3) – Chris 2013-04-22 00:37:44

回答

2

您必須等待或測試或由MPI_Isend()創建的MPI請求上的東西,否則您將泄漏內部資源,並最終崩潰,這就是發生了什麼事情。

Jeff Squyres在他的blog post at Cisco中表現很好。

知道,那些Isends正在完成,但MPI庫沒有知道這和清理分配資源的方式,並指出這些MPI_Request秒。需要多少資源和哪種資源取決於很多事情,包括底層網絡連接(例如可能佔用稀缺的infiniband資源),因此它在您自己的機器上工作而不是在羣集上工作並不一定意外。

您可以通過MPI_Isend/MPI_Recv() s各自階段之後加入

MPI_Waitall(2, request, status); 

解決這個問題。

這不僅僅是清理資源所必需的,它實際上還需要一個具有非阻塞請求的程序的正確性。

+0

的確,現在它的工作,謝謝。從來不知道這是必要的,我一直認爲你可以避免等待,如果你知道所有得到正確接收 – Chris 2013-04-24 09:41:35