Es sieht wie das Problem ist, dass Ihr lp
Objekt einen Zeiger enthält.
julia> lp = create_lp()
GLPK.Prob(Ptr{Void} @0x00007fa73b1eb330)
Leider mit Zeigern und Parallelverarbeitung arbeiten, ist schwierig - wenn unterschiedliche Prozesse unterschiedliche Speicherplätze haben dann ist es nicht klar ist, welche Speicheradresse der Prozess an, um aussehen sollte auf den Speicher zuzugreifen, dass der Zeiger zu.Diese Probleme können überwunden werden, aber sie erfordern offensichtlich individuelle Arbeit für jeden Datentyp, der diese Zeiger beinhaltet, siehe this GitHub-Diskussion für mehr.
Also mein Gedanke wäre, dass wenn Sie auf den Zeiger auf den Arbeiter zugreifen möchten, Sie es einfach auf diesem Arbeiter erstellen können. Z.B.
using GLPK
addprocs(2)
@everywhere begin
using GLPK
function create_lp()
lp = GLPK.Prob()
GLPK.set_prob_name(lp, "sample")
GLPK.term_out(GLPK.OFF)
GLPK.set_obj_dir(lp, GLPK.MAX)
GLPK.add_rows(lp, 3)
GLPK.set_row_bnds(lp,1,GLPK.UP,0,100)
GLPK.set_row_bnds(lp,2,GLPK.UP,0,600)
GLPK.set_row_bnds(lp,3,GLPK.UP,0,300)
GLPK.add_cols(lp, 3)
GLPK.set_col_bnds(lp,1,GLPK.LO,0,0)
GLPK.set_obj_coef(lp,1,10)
GLPK.set_col_bnds(lp,2,GLPK.LO,0,0)
GLPK.set_obj_coef(lp,2,6)
GLPK.set_col_bnds(lp,3,GLPK.LO,0,0)
GLPK.set_obj_coef(lp,3,4)
s = spzeros(3,3)
s[1,1] = 1
s[1,2] = 1
s[1,3] = 1
s[2,1] = 10
s[3,1] = 2
s[2,2] = 4
s[3,2] = 2
s[2,3] = 5
s[3,3] = 6
GLPK.load_matrix(lp, s)
return lp
end
end
a = @spawnat 2 eval(:(lp = create_lp()))
b = @spawnat 2 eval(:(result = simplex(lp)))
fetch(b)
Lesen Sie die Dokumentation unten auf @spawn
für weitere Informationen über die Verwendung es, da es ein wenig gewöhnungs nehmen.
Die Makros @spawn
und @spawnat
sind zwei der Werkzeuge, die Julia zuweisen Aufgaben für die Arbeitnehmer zur Verfügung stellt. Hier ein Beispiel:
julia> @spawnat 2 println("hello world")
RemoteRef{Channel{Any}}(2,1,3)
julia> From worker 2: hello world
Beide Makros wird eine expression auf einem Arbeitsprozess bewerten. Der einzige Unterschied zwischen den beiden ist, dass Sie mit @spawnat
auswählen können, welcher Mitarbeiter den Ausdruck auswerten wird (im obigen Beispiel wird Arbeiter 2 angegeben), während mit @spawn
ein Arbeiter automatisch ausgewählt wird, je nach Verfügbarkeit.
In dem obigen Beispiel hatten wir einfach Arbeiter 2 die Funktion println ausführen. Es gab nichts Interessantes, um davon zurückzukommen oder davon zurückzukommen. Oft jedoch wird der Ausdruck, den wir dem Arbeiter schicken, etwas ergeben, das wir abrufen wollen. Beachten Sie in dem obigen Beispiel, wenn wir @spawnat
aufgerufen, bevor wir den Ausdruck von Arbeiter 2, kamen, sahen wir folgendes:
RemoteRef{Channel{Any}}(2,1,3)
Dies zeigt an, dass das @spawnat
Makro ein RemoteRef
Typ Objekt zurück. Dieses Objekt enthält wiederum die Rückgabewerte aus unserem Ausdruck, der an den Worker gesendet wird. Wenn wir diese Werte abrufen möchten, können wir zuerst die RemoteRef
, die @spawnat
zurückgibt, einem Objekt zuweisen und dann die fetch()
-Funktion verwenden, die auf einem RemoteRef
-Objekt arbeitet, um die Ergebnisse aus einer an einem Worker ausgewerteten Auswertung abzurufen.
julia> result = @spawnat 2 2 + 5
RemoteRef{Channel{Any}}(2,1,26)
julia> fetch(result)
7
Der Schlüssel zum @spawn
effektiv Verständnis über die Natur hinter den expressions, dass es arbeitet, einsetzen zu können. Die Verwendung von @spawn
zum Senden von Befehlen an Worker ist etwas komplizierter, als wenn Sie direkt eingeben, was Sie eingeben würden, wenn Sie einen "Interpreter" auf einem der Worker ausführen oder nativ Code ausführen würden. Angenommen, wir möchten @spawnat
verwenden, um einer Variablen auf einem Worker einen Wert zuzuweisen. Wir könnten versuchen:
@spawnat 2 a = 5
RemoteRef{Channel{Any}}(2,1,2)
Hat es funktioniert? Nun, lassen Sie uns sehen, indem wir Arbeiter 2 versuchen, a
zu drucken.
julia> @spawnat 2 println(a)
RemoteRef{Channel{Any}}(2,1,4)
julia>
Nichts ist passiert. Warum? Wir können dies genauer untersuchen, indem wir fetch()
wie oben verwenden. fetch()
kann sehr praktisch sein, weil es nicht nur erfolgreiche Ergebnisse, sondern auch Fehlermeldungen abrufen wird. Ohne sie wissen wir vielleicht nicht einmal, dass etwas schiefgelaufen ist.
julia> result = @spawnat 2 println(a)
RemoteRef{Channel{Any}}(2,1,5)
julia> fetch(result)
ERROR: On worker 2:
UndefVarError: a not defined
Die Fehlermeldung besagt, dass a
nicht auf 2. Arbeitnehmer definiert ist, aber warum?Der Grund dafür ist, dass wir unsere Zuweisungsoperation in einen Ausdruck umbrechen müssen, den wir dann @spawn
verwenden, um den Worker zu bewerten. Unten ist ein Beispiel, mit Erklärung folgenden:
julia> @spawnat 2 eval(:(a = 2))
RemoteRef{Channel{Any}}(2,1,7)
julia> @spawnat 2 println(a)
RemoteRef{Channel{Any}}(2,1,8)
julia> From worker 2: 2
Die :()
Syntax ist das, was Julia expressions zu bezeichnen, verwendet. Wir verwenden dann die eval()
Funktion in Julia, die einen Ausdruck auswertet, und wir nutzen die @spawnat
Makro anzuweisen, dass der Ausdruck auf Arbeitnehmer bewertet 2.
konnten wir erreichen auch das gleiche Ergebnis wie:
julia> @spawnat(2, eval(parse("c = 5")))
RemoteRef{Channel{Any}}(2,1,9)
julia> @spawnat 2 println(c)
RemoteRef{Channel{Any}}(2,1,10)
julia> From worker 2: 5
Dieses Beispiel demonstriert zwei zusätzliche Begriffe. Zuerst sehen wir, dass wir auch einen Ausdruck mit der Funktion parse()
erstellen können, die für eine Zeichenfolge aufgerufen wird. Zweitens sehen wir, dass wir Klammern verwenden können, wenn wir @spawnat
aufrufen, in Situationen, in denen dies unsere Syntax klarer und überschaubarer machen könnte.
Können Sie ein reproduzierbares Beispiel veröffentlichen? –