2016-04-30 70 views
4

我在茱莉亞遇到了一個奇怪的錯誤。實質上,在某處添加print(「」)語句明智地改變了以下代碼的行爲(以一種積極的方式)。我很困惑。爲什麼?在茱莉亞的while循環中打印(「」)的效果

xs = [1,2,3,4,5,6,7,8] 

cmds = [`sleep $x` for x in xs] 

f = open("results.txt", "w") 

i = 1 
nb_cmds = length(cmds) 
max_running_ps = 3 
nb_running_ps = 0 
ps = Dict() 

while true 
    # launching new processes if possible 
    if nb_running_ps < max_running_ps 
     if i <= nb_cmds && !(i in keys(ps)) 
      print("spawn:") 
      println(i) 
      p = spawn(cmds[i], Base.DevNull, f, f) 
      setindex!(ps,p,i) 
      nb_running_ps = nb_running_ps + 1 
      i = i+1 
     end 
    end 
    # detecting finished processes to be able to launch new ones 
    for j in keys(ps) 
     if process_exited(ps[j]) 
      print("endof:") 
      println(j) 
      delete!(ps,j) 
      nb_running_ps = nb_running_ps - 1 
     else 
      print("") 
      # why do I need that ???? 
     end 
    end 
    # nothing runs and there is nothing to run 
    if nb_running_ps <= 0 && i > nb_cmds 
     break 
    end 
end 

close(f) 

println("finished") 

(實際上,命令實際上比睡眠更爲有用。)

如果打印( 「」)被去除或評論的,條件的內容「如果process_exited(PS [j]的)「似乎永遠不會運行,即使第一個max_running_ps進程已完成,程序也會運行到無限循環中。

一些背景:我需要運行一段需要很長時間才能運行(並使用大量內存)的代碼,用於一組參數的不同值(用x表示)。因爲他們需要很長時間,所以我想同時運行它們。另一方面,不同運行之間幾乎沒有什麼可分享的,所以通常的並行工具並不真正相關。最後,我想避免一個簡單的pmap,首先是爲了避免在失敗時丟失所有內容,其次是因爲在運行過程中獲得部分結果可能會有用。因此,這個代碼(寫在茱莉亞,因爲執行實際計算的主要代碼是在茱莉亞)。

+0

'print'是[asynchronous](http://docs.julialang.org/en/release-0.4/manual/networking-and-streams/)(出於性能的原因)和收益率。也許嘗試'@sync print(「」)'?如果這可以解決您的問題,那麼我會發布這個答案。 –

+0

事實上,我的問題已經通過添加print(「」)(即使沒有@sync)「解決」了。但是,我不明白爲什麼,因此我的問題。 –

+0

然後你的問題是相反的:你想要異步行爲(所以任務切換可以發生),並提供了打印。我會很快發佈答案。 –

回答

4

這不是一個錯誤,儘管如果你不習慣這種異步編程,這可能會令人驚訝。

Julia默認爲單線程,只有一個任務會一次運行。爲了完成任務,Julia需要切換到它。只要當前任務結束,就會切換任務。

print也是一個異步操作,所以它會讓你滿意,但更簡單的方法是yield(),它可以達到相同的結果。有關異步編程的更多信息,請參閱the documentation

+0

它確實有效。非常有趣,謝謝! –