2013-01-05 49 views
1

這是我第一次在這裏發佈,所以請原諒任何格式問題。STDIN似乎在打電話給「系統」後調用mpiexec

我有一個交互式程序,它產生外部進程並監視它們的IO。事情工作正常,直到我用「mpiexec」產生了一些東西,之後STDIN似乎中斷了。

我意識到這對大多數人來說很難重現,但如果任何人看到任何明顯的或知道這個問題....請幫助!

這裏有一個片段:

int main(...) 
{ 
    std::string choice; 
    while(std::getline(std::cin,choice)){ 
    if(!choice.empty()){ 
     if(choice == "Parallel"){ 
     system("mpiexec ./aprogram"); 
     } 
     if(choice == "Serial"){ 
     system("./aprogram"); 
     } 
     // Now the external process is done... so far, so good 
     std::cout << "Program is done. Press ENTER to continue." 
       << std::endl; 
     // This next line *works* if the external process was serial 
     // But *fails* when "mpiexec" was invoked 
     std::getline(std::cin,choice); 
     if(std::cin.eof()){ 
     std::cout << "STDIN has been closed." << std::endl; 
     exit(1); 
     } 
    } 
    } 
} 

我已經試過各種事情很多,例如管道,明確的分支,精細的描述符管理。最奇怪的是,如果我複製並保存stdin,然後在「mpiexec」返回後恢復它,那麼我不再在std :: cin上獲得EOF,而是std :: getline(std :: cin,...) )不再阻止!程序進入一個無限循環,在std :: readline調用中讀取std :: cin中的零字節。

如果當外部進程在mpiexec下運行時,我將一堆數據堆棧到std :: cin(例如,通過鍵入),然後對std :: readline的後續調用正確地解析了我卡住的數據行在那裏,但是再次......一旦讀完這些數據,它就會繼續進入一個無限循環(即不會阻止std :: readline(std :: cin,..),即使沒有數據閱讀!唉,太煩人。

任何幫助深表感謝。

乾杯!

+0

您在哪個平臺上使用哪種MPI實現? –

+0

我們目前在幾個不同的基於Linux的平臺(大多數是基於S.L.或CentOS的平臺)上使用基於MPICH的MPI實現(包括MVAPICH,vanilla MPICH2和MPICH-MX)。我還沒有嘗試過使用OpenMPI,但是這個集成系統中的一些應用程序對OpenMPI並不滿意。我相信問題必須圍繞「mpiexec」與STDIN所做的事情爲中心。我會嘗試獲得更好的片段,以便可以用香草mpich輕鬆複製。 – user1950175

+0

我可以用您的示例代碼和MPICH-3.0.1重現您的問題。我正在研究它。 –

回答

1

我想我能解決問題,對我來說無論是串行或通話並行堵塞,我想應該是的std :: cin.eof()測試,

std::getline(std::cin,choice); 
    if(std::cin.eof()){   
    td::cout << "STDIN has been closed." << std::endl; 
    exit(1); 
    } 

然而,改變這個爲std :: cin.get(),兩個並行運行,串行運行的偉大工程。

if(std::cin.get()) { 
    std::cout << "STDIN has been closed." << std::endl; 
    exit(1); 
    } 

適用於我的系統。

0

編輯:錯誤報告有moved to GitHub。好吧,這不是一個真正的答案,但我沒有足夠的聲望評論這個問題,顯然。

我和我的同事遇到了這個問題,並將其追查了一下。你必須跳過一大堆籃圈才能在mpich bug report上添加評論,但我不希望我的發現消失在以太網中,所以我在這裏添加它們。 (如果有人閱讀這篇文章,可以登錄mpich Trac,如果你可以將這些信息添加到票證中,那將是非常棒的。)

Mpich確實似乎有一個bug,它在stdout/stderr文件上設置了O_NONBLOCK標誌mpirun在常用模式下的描述符。這些設置在mpirun退出後繼續存在。但是,此錯誤通常不會出現,因爲bash的代碼會在其運行的每條命令(如有必要)之後將其附加流的非阻塞標誌從關閉。

mpirun中直接負責的代碼位於alloc_fwd_hashsrc/pm/hydra/utils/sock.sock.c中。它由HYDT_bscd_common_launch_procs函數中src/pm/hydra/tools/bootstrap/external/external_common_launch.c等地方的代碼觸發,其中有一些分路器註冊步驟涉及最終調用alloc_fwd_hash函數的回叫HYDT_bscu_stdio_cb。還有一些其他類似的代碼也可以設置回調,並且通過閱讀代碼,應該引發同樣的問題。我不太瞭解mpich以瞭解哪個部分有問題,但我確實認爲mpich將TTY文件描述符設置爲非阻塞模式是不恰當的。

您可以通過在OS X上使用Homebrew構建的bash運行mpirun來觸發此錯誤。 Homebrew的bash是4.4版本,由於我不完全清楚的原因,似乎沒有激活清除O_NONBLOCK標誌的代碼片段。 OSX上的bash的默認版本是版本3,其中的作用是清除標誌,防止出現故障。 Bash 4的Macports版本也顯示了這個錯誤。