2009-10-28 3 views
18

Je suis en train d'exécuter le programme suivant, qui calcule les racines de polynômes de degré jusqu'à d avec coefficients seulement +1 ou -1, puis les stocker dans des fichiers.Mathematica à court de mémoire

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

Ici f [z, i] donne un polynôme en z avec plus ou moins de signes de comptage en binaire. Dire d = 2, nous aurions

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}] 

Je réalise en train de lire ce qui est probablement pas trop agréable , mais c'est relativement court de toute façon. J'aurais essayé de réduire les parties pertinentes, mais ici, je n'ai vraiment aucune idée de ce que le problème est. Je calcule toutes les racines de f [z, i], puis les arrondis juste pour les faire correspondre à un point dans une grille n par n, et sauvegardons ces données dans divers fichiers.

Pour une raison quelconque, l'utilisation de la mémoire dans Mathematica se poursuit jusqu'à remplir toute la mémoire (6 Go sur cette machine); alors le calcul continue extrêmement lentement; Pourquoi est-ce? Je ne suis pas sûr de ce qui utilise la mémoire ici - mon seul doute était le flux de fichiers utilisés, mais ce n'est pas le cas: j'ai essayé d'ajouter des données à des fichiers de 2 Go et il n'y avait pas d'utilisation de la mémoire pour cela . Mathematica n'a absolument aucune raison d'utiliser de grandes quantités de mémoire ici.

Pour les petites valeurs de d (15 par exemple), le comportement est le suivant: J'ai 4 noyaux en cours d'exécution. Comme ils passent tous par la boucle ParallelDo (chacun faisant une valeur de j à la fois), l'utilisation de la mémoire augmente, jusqu'à ce qu'ils finissent tous une fois par cette boucle. Ensuite, la prochaine fois qu'ils passent par cette boucle, l'utilisation de la mémoire n'augmente pas du tout. Le calcul finit par se terminer et tout va bien.

Également, très important, une fois le calcul arrêté, l'utilisation de la mémoire ne redescend pas. Si je commence un autre calcul, les événements suivants se produisent:

-Si le calcul précédent s'est arrêté lorsque l'utilisation de la mémoire était encore en augmentation, il continue d'augmenter (il peut falloir un certain temps pour recommencer à augmenter, essentiellement pour atteindre le même point dans le calcul).

-Si le calcul précédent s'est arrêté lorsque l'utilisation de la mémoire n'augmentait pas, elle n'augmente plus.

Editer: Le problème semble provenir de la complexité relative de f - le changer en un polynôme plus facile semble résoudre le problème. J'ai pensé que le problème pourrait être que Mathematica se souvient de f [z, i] pour des valeurs spécifiques de i, mais en mettant f [z, i]: =. juste après avoir calculé une racine de f [z, i] se plaint que l'assignation n'existait pas en premier lieu, et la mémoire est toujours utilisée. C'est vraiment déroutant, car f est la seule chose que je puisse imaginer en train de prendre de la mémoire, mais définir f dans la boucle Do interne et l'effacer chaque fois qu'une racine est calculée ne résout pas le problème.

+0

Avez-vous essayé d'exécuter cet algorithme avec des valeurs d plus petites, voire individuelles? –

+0

Je viens d'ajouter un paragraphe décrivant ce qui se passe pour les plus petits d. –

+0

Que se passe-t-il lorsque vous exécutez le programme sans ouvrir le flux, effectuer les écritures et fermer le flux (c'est-à-dire sans E/S)? – Pillsy

Répondre

11

Ouch, c'est un méchant.

Ce qui se passe est que N fera la mise en cache des résultats afin d'accélérer les calculs futurs si vous en avez besoin à nouveau. Parfois, c'est absolument ce que vous voulez, mais parfois cela brise le monde. Heureusement, vous avez quelques options. L'une consiste à utiliser la commande ClearSystemCache, qui fait exactement ce qu'elle dit sur l'étain. Après avoir couru votre boucle non-parallélisée pendant un petit moment (avant de s'ennuyer et d'abandonner le calcul), MemoryInUse a rapporté ~ 160 MiB en cours d'utilisation. L'utilisation de ClearSystemCache l'a ramené à environ 14 Mio.

Une chose que vous devriez regarder faire, au lieu d'appeler ClearSystemCache par programme, est d'utiliser SetSystemOptions pour changer le comportement de mise en cache. Vous devriez jeter un oeil à SystemOptions["CacheOptions"] pour voir quelles sont les possibilités.

EDIT: Il n'est pas vraiment surprenant que la mise en cache provoque un problème plus important pour les expressions plus complexes. Il doit y avoir des copies de ces expressions quelque part, et des expressions plus complexes nécessitent plus de mémoire.

+0

Hmm, j'ai de la difficulté à reproduire vos résultats. Pour le moment, deux problèmes se produisent: dans la version non-parallèle, lorsque j'appelle ClearSystemCache, MemoryInUse signale que la mémoire utilisée est redescendue, mais le gestionnaire de tâches montre que le noyau utilise toujours autant de mémoire. Deuxièmement, en mode parallélisé, je ne trouve pas l'option pour effacer le cache des noyaux individuels. Mais vous sembliez avoir trouvé la cause précise, maintenant il s'agit plutôt de trouver comment la traiter. –

+0

Messing avec les CacheOptions ne s'est pas révélé non plus fructueux - j'ai tout mis à la taille des octets faux et max à 0 et cela n'a fait aucune différence (à la version non-parallèle et donc pas de différence à la version parallélisée non plus). –

+0

Ok, l'ajout de ClearSystemCache fonctionne réellement; pour une raison quelconque, cela n'a pas fonctionné la première fois, mais maintenant cela fonctionne. Cela fonctionne même dans la version parallèle. Merci! –

Questions connexes