2012-01-22 33 views
2

我正在使用一組計算機來執行一些並行計算。我的主目錄在羣集中共享。在一臺機器上,我有一個ruby代碼,它創建包含計算命令的bash腳本,並將腳本寫入〜/ q /目錄。這些腳本被命名爲* .worker1.sh,* .worker2.sh等。Python(或者一般的linux)文件操作流程控制或文件鎖定

在其他20臺機器上,我有20個python代碼運行(每臺機器一個),(不斷)檢查〜/ q /目錄並尋找屬於該機器的工作,使用Python代碼是這樣的:在

jobs = glob.glob('q/*.worker1.sh') 
[os.system('sh ' + job + ' &') for job in jobs] 

對於一些額外的控制,Ruby代碼將創建像workeri.start一個空文件(I = 1..20) q目錄後,它將bash腳本寫入q目錄,python代碼將在運行上述代碼之前檢查該「開始」文件。在bash腳本中,如果命令成功完成,bash腳本將創建一個像'workeri.sccuess'這樣的空文件,python代碼在運行上述代碼後檢查該文件,以確保計算成功完成。如果python發現計算成功完成,它將刪除q目錄中的'start'文件,以便Ruby代碼知道該作業成功完成。 20 bash腳本全部完成後,ruby代碼將創建新的bash腳本和python讀取並執行新的腳本等。

我知道這不是一種優雅的方式來協調計算,但我還沒有找到更好的溝通不同的機器之間。

現在的問題是:我預計20個職位會有點平行。完成20個工作的總時間不會比完成一份工作的時間長得多。但是,看起來這些作業是按順序運行的,而且時間比我預期的要長得多。

我懷疑,部分原因是多個代碼讀取和寫入一次相同的目錄,但Linux系統或Python鎖目錄,只允許一個進程oprate目錄。這使得代碼一次執行一個。

我不確定是否屬於這種情況。如果我將bash腳本分割到不同的目錄中,並讓不同機器上的python代碼讀取和寫入不同的目錄,是否可以解決問題?還是有其他原因導致問題?

非常感謝您的任何建議!如果我沒有清楚解釋什麼,請告訴我。

一些額外的信息: 我的主目錄是/家/ my_group/my_home,這裏是它 安裝信息:上/家庭/ my_group類型NFS /體積/ my_group(RW,爲nosuid,nodev,noatime的, TCP,Timeo酒店= 600,重傳= 2,RSIZE = 65536,WSIZE = 65536,地址= ...)

我說經常檢查將q目錄,這意味着一個Python循環是這樣的:

While True: 
    if 'start' file exists: 
     find the scripts and execute them as I mentioned above 
+0

什麼文件系統和安裝選項? – sarnold

+0

...並且當你說_持續檢查'〜/ q /'目錄時,你是否真的意味着**不斷**?如在[忙碌圈]中(http://en.wikipedia.org/wiki/Busy_loop)? – sarnold

+0

@sarnold我的主目錄應物理地位於單獨的文件服務器上。我相信這是ext3文件系統。以下是我在羣集的登錄節點上mount問題後得到的信息:/ vol/my_group在/ home/my_group類型nfs(rw,nosuid,nodev,noatime,tcp,timeo = 600,retrans = 2,rsize = 65536,wsize = 65536,addr = ...)我的主目錄是/ home/my_group/my_home/ – qkhhly

回答

1

我知道這是不是協調計算一個優雅的方式,但我 還沒有想出一個更好地溝通不同的 機器。

雖然這不是直接問你什麼,你真的應該,真的考慮在這個級別修復您的問題,使用某種共享的消息隊列的很可能是一個很多易於管理和調試而不是依賴特定網絡文件系統的鎖定語義。

根據我的經驗設置和運行的最簡單的解決方案是當前運行創建作業的Ruby腳本的機器上的redis。它應該像下載源文件,編譯它並啓動它一樣簡單。 Redis服務器啓動並運行後,您將更改代碼以將計算命令附加到一個或多個Redis列表中。在Ruby中,你將使用redis-rb庫這樣的:

require "redis" 

redis = Redis.new 
# Your other code to build up command lists... 
redis.lpush 'commands', command1, command2... 

如果計算需要由某些機器來處理,這樣使用的每臺機器的列表:在

redis.lpush 'jobs:machine1', command1 
# etc. 

然後你Python代碼,你可以使用redis-py連接到Redis的服務器和拉斷的工作列表,像這樣:

from redis import Redis 
r = Redis(host="hostname-of-machine-running-redis") 
while r.llen('jobs:machine1'): 
    job = r.lpop('commands:machine1') 
    os.system('sh ' + job + ' &') 

當然,你可以很輕鬆地將工作從隊列和執行它們在Ruby中:

require 'redis' 
redis = Redis.new(:host => 'hostname-of-machine-running-redis') 
while redis.llen('jobs:machine1') 
    job = redis.lpop('commands:machine1') 
    `sh #{job} &` 
end 

隨着對計算和它的運行環境的需要一些更多的細節,這將有可能推薦甚至更簡單的管理方法。

+0

聽起來像是一個很好的解決方案,我會檢查出來。作業不必在特定的機器上運行。它沒有任何特定的腳本語言。實際的計算是由一個c程序完成的,這是我在bash腳本中提到的命令。我唯一需要的是多次計算(本例中爲20)應該儘快完成。集羣由我開始討厭的Sun Grid Engine管理。 – qkhhly

+0

我並不熟悉Sun Grid Engine,但它似乎應該能夠爲您計劃計算,而不需要設置自己的工作隊列(我在回答中推薦的內容)。它看起來像支持並行作業的概念,qrsh和qtcsh shell應該能夠運行你的程序。我會詢問您的管理員或羣集的其他用戶在使用其提供的工具時尋求幫助或文檔。 – grncdr

+0

Sun Grid Engine確實有一個隊列系統,但我的作業很短,但數量很多。基本上排隊等待的時間比計算長得多。所以我沒有從多臺機器中受益。我需要自己協調計算,而不是使用SGE隊列系統。我嘗試了你所建議的方法,結果很棒!非常感謝你! – qkhhly

0

嘗試一段時間循環?如果還是不行,在Python端嘗試使用try語句像這樣:

Try: 
    with open("myfile.whatever", "r") as f: 
      f.read() 
except: 
    (do something if it doesnt work, perhaps a PASS? (must be in a loop to constantly  check this) 

else: 
    execute your code if successful