2016-04-30 6 views
4

Ich habe einen seltsamen Fehler in Julia gefunden. Im Wesentlichen ändert das Hinzufügen einer Druckanweisung ("") irgendwo das Verhalten des folgenden Codes (im positiven Sinne). Ich bin ziemlich verwirrt. Warum?Effekt des Drucks ("") in einer While-Schleife in Julia

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") 

(Tatsächlich sind die Befehle in der Tat nützlicher als Schlaf.)

Wenn der Druck ("") entfernt wird oder kommentiert, wird der Inhalt des bedingten „wenn process_exited (ps [j]) "scheint nie zu laufen, und das Programm läuft in eine unendliche while-Schleife, obwohl die ersten max_running_ps-Prozesse beendet sind.

Einige Hintergrund: Ich brauche ein Stück Code, der eine ziemlich lange Zeit zu laufen braucht (und eine Menge Speicher verwendet), für verschiedene Werte eines Satzes von Parametern (hier durch x dargestellt). Da sie lange brauchen, möchte ich sie parallel laufen lassen. Auf der anderen Seite gibt es fast nichts zu teilen zwischen den verschiedenen Läufen, so dass die üblichen parallelen Tools nicht wirklich relevant sind. Schließlich möchte ich ein einfaches pmap vermeiden, um erstens alles zu vermeiden, wenn es einen Fehler gibt, und zweitens, weil es nützlich sein kann, während des Laufs partielle Ergebnisse zu haben. Daher dieser Code (geschrieben in Julia, weil der Hauptcode, der die tatsächlichen Berechnungen durchführt, in Julia ist).

+0

'print' ist [asynchron] (http://docs.julaulang.org/en/release-0.4/manual/networking-and-streams/) (aus Leistungsgründen) und ergibt. Vielleicht probier '@sync print ("") stattdessen? Wenn das dein Problem behebt, poste ich das als Antwort. –

+0

In der Tat ist mein Problem bereits "gelöst" durch Hinzufügen des Ausdrucks ("") (auch ohne @sync). Allerdings verstehe ich nicht warum, daher meine Frage. –

+0

Dann ist das Problem das Gegenteil: Sie wollen asynchrones Verhalten (so kann ein Taskwechsel auftreten), und Print bietet das. Ich werde bald eine Antwort schreiben. –

Antwort

4

Dies ist kein Fehler, obwohl es überraschend sein könnte, wenn Sie diese Art der asynchronen Programmierung nicht gewohnt sind.

Julia ist standardmäßig single-threaded und nur eine Aufgabe wird gleichzeitig ausgeführt. Und um eine Aufgabe zu beenden, muss Julia zu ihr wechseln. Aufgaben werden gewechselt, wenn die aktuelle Aufgabe nachgibt.

print ist auch eine asynchrone Operation und so wird es für Sie ergeben, aber ein einfacher Weg, es zu tun ist yield(), die das gleiche Ergebnis erzielt. Weitere Informationen zur asynchronen Programmierung finden Sie unter the documentation.

+0

Es funktioniert tatsächlich. Sehr interessant, danke! –