2009-10-28 10 views
18

Estoy intentando ejecutar el siguiente programa, que calcula las raíces de polinomios de grado hasta d con coeficientes solo +1 o -1, y luego lo almacena en archivos.Mathematica quedando sin memoria

d = 20; n = 18000; 
f[z_, i_] := Sum[(2 Mod[Floor[(i - 1)/2^k], 2] - 1) z^(d - k), {k, 0, d}]; 

Aquí f [z, i] da un polinomio en z con signos más o menos Cuenta en binario. Say d = 2, tendríamos

f [z, 1] = -z - z - 1
f [z, 2] = -z - z + 1
f [ z, 3] = -z + z - 1
f [z, 4] = -z + z + 1

DistributeDefinitions[d, n, f] 

ParallelDo[ 
      Do[ 
        root = N[Root[f[z, i], j]]; 
        {a, b} = Round[n ({Re[root], Im[root]}/1.5 + 1)/2]; 
      {i, 1, 2^d}], 
{j, 1, d}] 

Soy consciente leyendo esto probablemente no es demasiado agradable , pero es relativamente corto de todos modos. Hubiera tratado de reducir las partes relevantes, pero aquí realmente no tengo idea de cuál es el problema. Estoy calculando todas las raíces de f [z, i], y luego simplemente las rodeo para que correspondan a un punto en una cuadrícula n por n, y guardo esos datos en varios archivos.

Por alguna razón, el uso de la memoria en Mathematica se arrastra hasta que llena toda la memoria (6 GB en esta máquina); entonces el cálculo continúa extremadamente lento; ¿Por qué es esto?

No estoy seguro de qué es lo que está usando la memoria aquí; mi única conjetura era la secuencia de archivos usados ​​en la memoria, pero ese no es el caso: intenté anexar datos a archivos de 2GB y no había uso de memoria notable para eso . No parece haber ninguna razón para que Mathematica esté usando grandes cantidades de memoria aquí.

Para valores pequeños de d (15 por ejemplo), el comportamiento es el siguiente: Tengo 4 núcleos en ejecución. Como todos corren a través del bucle ParallelDo (cada uno haciendo un valor de j a la vez), el uso de la memoria aumenta, hasta que todos terminan de atravesar ese bucle una vez. Luego, las próximas veces que pasan por ese ciclo, el uso de la memoria no aumenta en absoluto. El cálculo finalmente termina y todo está bien.

También, lo que es más importante, una vez que se detiene el cálculo, el uso de la memoria no baja. Si empiezo otro cálculo, sucede lo siguiente:

-Si el cálculo anterior se detuvo cuando el uso de la memoria aún aumentaba, continúa aumentando (puede llevar un tiempo volver a aumentar, básicamente para llegar al mismo punto en el cálculo).

-Si el cálculo anterior se detuvo cuando el uso de la memoria no aumentaba, no aumenta más.

Editar: El problema parece provenir de la complejidad relativa de f - cambiarlo a un polinomio más fácil parece solucionar el problema. Pensé que el problema podría ser que Mathematica recuerda f [z, i] para valores específicos de i, pero estableciendo f [z, i]: =. justo después de calcular una raíz de f [z, i] se queja de que la asignación no existía en primer lugar, y la memoria aún se usa.

Realmente es bastante desconcertante, ya que f es lo único que me queda en la memoria, pero definir f en el bucle Do interno y borrarlo cada vez que se calcula una raíz no resuelve el problema.

+0

¿Ha intentado ejecutar este algoritmo con valores d más pequeños o incluso individuales? –

+0

Acabo de agregar un párrafo que describe lo que sucede para los más pequeños d. –

+0

¿Qué sucede cuando ejecuta el programa sin abrir la secuencia, hacer las escrituras y cerrar la secuencia (es decir, sin ninguna E/S)? – Pillsy

Respuesta

11

Ouch, esta es una desagradable.

Lo que está sucediendo es que N hará el almacenamiento en caché de los resultados para acelerar los cálculos futuros si los necesita de nuevo. A veces esto es absolutamente lo que quieres, pero a veces simplemente rompe el mundo. Afortunadamente, tienes algunas opciones. Una es usar el comando ClearSystemCache, que hace exactamente lo que dice en la lata. Después de ejecutar su ciclo no paralelizado durante un tiempo (antes de aburrirme y abortar el cálculo), MemoryInUse informó ~ 160 MiB en uso. Usando ClearSystemCache bajé a alrededor de 14 MiB.

Una cosa que debe considerar hacer, en lugar de llamar ClearSystemCache mediante programación, es usar SetSystemOptions para cambiar el comportamiento de almacenamiento en caché. Deberías echar un vistazo al SystemOptions["CacheOptions"] para ver cuáles son las posibilidades.

EDITAR: No es terriblemente sorprendente que el almacenamiento en caché cause un problema mayor para expresiones más complejas. Tiene que esconder copias de esas expresiones en alguna parte, y las expresiones más complejas requieren más memoria.

+0

Hmm, tengo problemas para copiar los resultados. Por el momento, ocurren dos problemas: en la versión sin paralelo, cuando llamo a ClearSystemCache, MemoryInUse informa que la memoria en uso ha vuelto a bajar, pero el administrador de tareas muestra que el kernel sigue usando tanta memoria. En segundo lugar, en el modo paralelizado, no puedo encontrar la opción para borrar el caché de los núcleos individuales. Pero parecías haber encontrado la causa exacta, ahora es más una cuestión de encontrar cómo tratarla. –

+0

Meterse con las CacheOptions tampoco resultó ser fructífero: establecí todo en tamaños de bytes falsos y máximos en 0 y no importó (a la versión sin paralelo, por lo que tampoco hay diferencias con la versión paralelizada). –

+0

Ok, agregando ClearSystemCache de hecho funciona; por alguna razón, no funcionó la primera vez, pero ahora funciona. Incluso funciona en la versión paralela. ¡Gracias! –

Cuestiones relacionadas