2011-12-15 35 views
9

A volte quando sto scrivendo codice sperimentale in Mathematica, sono cauto sul fatto che dovrei valutarlo o meno perché potrebbe finire per portare il mio sistema alle sue ginocchia.Valutazione asincrona in Mathematica

Come esempio forzato se si tenta di eseguire il seguente snippet di codice su un computer a 64 bit, molto probabilmente causerà il blocco del sistema dopo un'interruzione completa della memoria.

junk = Table[{x, x}, {10^9}]; (* nom nom nom memory. Please don't run this. *) 

Certo, si può semplicemente gettare MemoryConstrained su di esso e sperare per il meglio, ma a volte non lo vogliono bloccare qualsiasi ulteriore input. A tal fine, il modo in cui pensavo fosse meglio raggiungere una via di mezzo era eseguire la valutazione in un kernel separato.

Quello era decentemente abbastanza facile da fare:

ClearAll[GetAvailableKernel]; 
GetAvailableKernel[] := Block[{i, kernels}, 
    kernels = Kernels[]; 
    If[[email protected] != 0, 
    For[i = 1, i <= [email protected], i++, 
    If[kernels[[i, 1, 2]] > 0, [email protected][[i]]] 
    ] 
    ]; 
    LaunchKernels[1]] 

ClearAll[SafeEvaluate]; 
SetAttributes[SafeEvaluate, HoldFirst]; 
Options[SafeEvaluate] = {"EvaluationKernel" -> Null, 
    "ConstrainMemory" -> True, "MaxMemory" -> 2 1024^3}; 

SafeEvaluate[expr_, OptionsPattern[]] := Block[{evalkernel, result}, 
    If[OptionValue["EvaluationKernel"] != Null, 
    evalkernel = OptionValue["EvaluationKernel"], 
    evalkernel = GetAvailableKernel[] 
    ]; 

    result = If[OptionValue["ConstrainMemory"], 
    With[{memory = OptionValue["MaxMemory"]}, 
    ParallelEvaluate[MemoryConstrained[expr, memory], evalkernel]], 
    ParallelEvaluate[expr, evalkernel]]; 
    result] 

Poi si può solo andare avanti e fare qualcosa sulla falsariga di:

SafeEvaluate[Table[{x, x}, {1024^3}]] 

E Mathematica sarebbe tornato con grazia $Aborted che indica che correva fuori dalla memoria. Valutando in un kernel separato, possiamo inserire il codice sandbox nel proprio kernel parallelo. Se qualcosa va storto, allora il nostro kernel principale non è interessato.


Questo mi porta al mio punto principale: Come posso ottenere la valutazione asincrono all'interno di Mathematica?

Quello che ho ora funziona, ma blocca completamente ogni ulteriore input da parte dell'utente. Non posso semplicemente impostare, dimenticare e controllare più tardi.

Qualche idea?

+0

È elaborato descrivere 'SafeEvaluate' ancora si spende qualche parola sul vostro attuale domanda e sono lasciato a indovinare il suo significato. Stai cercando un modo per valutare un'espressione in una cella, lasciare la valutazione in esecuzione e valutare un'espressione in una seconda cella, ottenendo potenzialmente il risultato prima che la valutazione della prima cella venga completata? –

+0

@ Mr.Wizard Questa è la mia lettura della domanda. Il mio primo pensiero è che questo è impossibile perché qualsiasi valutazione cambierà lo stato del kernel. Quindi due valutazioni parallele cambierebbero in modo similitudinale lo stato del kernel: Mike sta infatti chiedendo il multithreading, con tutte le difficoltà e sottigliezze che fa emergere. (Anche con i kernel paralleli, parte dello stato viene condivisa anche per ottenere i risultati.) Ma poi ho pensato a 'Dynamic [f [i]]', 'Table [Pause [1]; i, {i, 10}] '(provalo --- è come' Monitor'). In realtà questo sta valutando le cose in parallelo, in un singolo kernel. – Szabolcs

+0

@Szabolcs dove dice che vuole una valutazione parallela all'interno di un singolo kernel? –

risposta

7

devo prossima allo zero esperienza con il calcolo parallelo in Mathematica, quindi questo potrebbe non essere il modo migliore, ma questo è quello che sono riuscito a scavare from the docs:

lancio un kernel:

In[1]:= LaunchKernels[1] 

Out[1]= KernelObject[1, "local"] 

Invia un po 'lungo per finire lavoro:

In[2]:= job = 
ParallelSubmit[[email protected][RandomReal[1, {2000, 2000}]]] 

Mathematica graphics

lavoro

Inizio:

In[3]:= Parallel`Developer`QueueRun[] 

Out[3]= True 

Ora il processo è in esecuzione in parallelo sullo sfondo ...

Mathematica graphics

... e siamo liberi di fare quello che vogliamo nella principale kernel. Se capisco la tua domanda, questo è quello che ti serviva. Possiamo eseguire nuovamente Parallel`Developer`QueueRun[] per verificare quali valutazioni parallele siano terminate (la visualizzazione dell'oggetto di valutazione verrà aggiornata dinamicamente).

In[4]:= 1 + 1 

Out[4]= 2 

attendere il termine di valutazione (se non lo ha ancora) e raccogliere il risultato:

In[5]:= WaitAll[job] 

Out[5]= 1000.23 

Mathematica graphics

+0

Un'altra serie di funzioni che non ho usato. +1 solo per quello! –

+0

@ Mr.Wizard Innanzitutto volevo fare qualcosa di simile all'esempio [qui] (http://reference.wolfram.com/mathematica/ref/EvaluatePacket.html), poi mi sono reso conto che sarebbe stata ri-implementare la funzionalità di parallelizzazione (che ha già 'DistributeDefinitions'!), quindi ho cercato ancora una volta i documenti. Neanche io conoscevo queste funzioni. – Szabolcs

0

Era molto tempo fa che usavo Mathematica ma avevo un'idea. Per quanto ne so, puoi impostare la valutazione automatica della funzione quando carichi un documento Mathematica. Non sarebbe possibile utilizzare Mathematica per creare un documento con la funzione SafeEvalutazione [funzione] come "esegui al caricamento" e avviare un altro processo Mathematica in background con questo documento. Quindi puoi ancora usare quello che vedi per l'input. Naturalmente, sarà necessario riunire tale processo per vedere se è terminato, o fare in modo che la funzione che valuta salvi un file risultato che si raggruppa.

3

Molto spesso ciò che accade è che il sistema esaurirà la memoria e inizierà a scambiare. E lo scambio farà morire lentamente il sistema. Su Linux qui è quello che faccio

alias m804='ulimit -v 3800000; /usr/local/bin/math8.0.4/mathematica' 

Il sistema, quindi, dà solo il messaggio Memoria e chiude prima che va da scambiare. Altrimenti si comporta come al solito.

+0

Qualcosa per Windows? http://stackoverflow.com/questions/7854980/correct-way-to-cap-mathematica-memory-use –

+0

Io non sono una persona Windows, qualcun altro avrebbe bisogno di commentare su questo argomento. –

+0

Ho provato a usare 'ulimit' un paio di volte per scopi diversi e non funziona mai veramente su un mac. Su Linux, penso che sia necessario disporre dei privilegi di amministratore, motivo per cui non sono riuscito a farlo funzionare sul mio server di gruppo. – abcd