2011-12-15 12 views
9

A veces, cuando estoy escribiendo código experimental en Mathematica, soy cauteloso sobre si debería evaluarlo o no, porque puede terminar llevando mi sistema a sus rodillas.Evaluación asíncrona en Mathematica

Como ejemplo artificioso si se intenta ejecutar el siguiente fragmento de código en una máquina de 64 bits, lo más probable es hacer que el sistema para moler a un alto completo después de que se consume toda la memoria.

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

Claro, usted puede simplemente tirar MemoryConstrained a ella y esperar lo mejor, pero a veces no desea que el bloqueo de ninguna entrada adicional. Con ese fin, la forma en que pensé que sería mejor lograr un término medio fue realizar la evaluación en un núcleo separado.

Eso era bastante bastante fácil de hacer:

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] 

A continuación, sólo puede seguir adelante y hacer algo en la línea de:

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

y Mathematica volvería con gracia $Aborted le dice que corrió sin memoria. Al evaluar en un kernel por separado, podemos codificar sandbox en su propio kernel paralelo. Si algo sale mal, nuestro kernel principal no se verá afectado.


Esto me lleva a mi punto principal: ¿Cómo puedo lograr Evaluación asíncrona dentro de Mathematica?

Lo que tengo ahora funciona, pero bloquea por completo cualquier entrada de usuario. No puedo simplemente establecer, olvidar y verificar más tarde.

¿Alguna idea?

+0

Se describe detalladamente 'SafeEvaluate' sin embargo, que pasan unas palabras en su real pregunta y me queda adivinar su significado. ¿Está buscando una manera de evaluar una expresión en una celda, dejar ejecutándose la evaluación y evaluar una expresión en una segunda celda, obteniendo potencialmente el resultado antes de que se complete la evaluación de la primera? –

+0

@ Mr.Wizard Esa es mi lectura de la pregunta. Lo primero que pensé fue que esto es imposible porque cualquier evaluación cambiará el estado del kernel. Por lo tanto, dos evaluaciones paralelas cambiarían simulaimente el estado del kernel: Mike en realidad está pidiendo multithreading, con todas las dificultades y sutilezas que trae aparejadas. (Incluso con kernels paralelos, algunos de los estados se comparten para obtener los resultados). Pero luego pensé en 'Dynamic [f [i]]', 'Table [Pause [1]; i, {i, 10}] '(pruébalo --- es como' Monitor'). De hecho, esto es evaluar cosas en paralelo, en un solo kernel. – Szabolcs

+0

@Szabolcs ¿dónde dice que quiere una evaluación paralela dentro de un kernel único? –

Respuesta

7

que tienen próxima a cero experiencia con computación en paralelo en Mathematica, así que esto podría no ser la mejor manera, pero esto es lo que he conseguido desenterrar from the docs:

lanzamiento de un núcleo:

In[1]:= LaunchKernels[1] 

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

Presentar algunos tiempo para terminar el trabajo:

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

Mathematica graphics

trabajo

de inicio:

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

Out[3]= True 

Ahora el trabajo se está ejecutando en paralelo en el fondo ...

Mathematica graphics

... y somos libres de hacer lo que queramos en el principal núcleo. Si entiendo tu pregunta, esto es lo que necesitabas. Podemos ejecutar Parallel`Developer`QueueRun[] nuevamente para verificar qué evaluaciones paralelas han finalizado (la visualización del objeto de evaluación se actualizará dinámicamente).

In[4]:= 1 + 1 

Out[4]= 2 

esperar hasta que el de evaluación (si no lo ha hecho todavía) y recoger el resultado:

In[5]:= WaitAll[job] 

Out[5]= 1000.23 

Mathematica graphics

+0

Otro conjunto de funciones que no he usado. +1 por eso solo! –

+0

@ Mr.Wizard Primero quise hacer algo similar al ejemplo [aquí] (http://reference.wolfram.com/mathematica/ref/EvaluatePacket.html), luego me di cuenta de que estaría reaplicando la funcionalidad de paralelización (¡que ya tiene 'DistributeDefinitions'!), así que busqué en los documentos un poco más. Yo tampoco conocía estas funciones. – Szabolcs

0

Hace mucho tiempo que utilicé Mathematica pero tuve una idea. Por lo que sé, puede establecer una evaluación automática de la función cuando carga un documento de Mathematica. No sería posible usar Mathematica para crear un documento con su SafeEvaluate [función] como "ejecutar al cargar" e iniciar otro proceso de Mathematica en el fondo con este documento. Entonces todavía puedes usar el que ves para la entrada. Por supuesto, entonces tendrá que agrupar ese proceso para ver si terminó, o tener la función que evalúa guardar un archivo de resultados que haya agrupado.

3

Muy a menudo lo que sucede es que su sistema se quedará sin memoria y comenzará a intercambiar. Y el intercambio hará que el sistema muera lentamente. En Linux aquí es lo que hago

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

El sistema simplemente da el mensaje de falta de memoria y se cierra antes de pasar al intercambio. De lo contrario, se comporta como de costumbre.

+0

¿Algo para Windows? http://stackoverflow.com/questions/7854980/correct-way-to-cap-mathematica-memory-use –

+0

No soy una persona de Windows, alguien más tendría que comentar sobre este asunto. –

+0

He intentado usar 'ulimit' varias veces para diferentes propósitos y nunca funciona realmente en un mac. En Linux, creo que debes tener privilegios de administrador, por lo que no pude ejecutarlo en mi servidor de grupo. – abcd