Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak with beam_parse method #4432

Closed
DDouteaux opened this issue Oct 11, 2019 · 7 comments · Fixed by #4686
Closed

Memory leak with beam_parse method #4432

DDouteaux opened this issue Oct 11, 2019 · 7 comments · Fixed by #4686
Labels
bug Bugs and behaviour differing from documentation feat / ner Feature: Named Entity Recognizer perf / memory Performance: memory use

Comments

@DDouteaux
Copy link

DDouteaux commented Oct 11, 2019

How to reproduce the behaviour

We are currently trying to obtain a confidence score for entities found with NER. In order to do so, we implement the solution that was suggested in these places :

The code is performing well for the functionality, but unfortunately implies a memory leak, as suggested by @usamec in the thread #881 . The first code was produced for SpaCy 2.0 and we first thought that it might have been corrected in newest releases, so we perform tests with version 2.2 but with same results.

Here is the code used to highlight the memory leak :

# Imports for SpaCy
import spacy
from spacy.tokens import Doc
from spacy.pipeline import EntityRecognizer

# Imports for debug
import psutil
import os
import time

# Imports for drawing
import matplotlib.pyplot as plt

# Miscellaneous
from collections import defaultdict

nlp = spacy.load("fr_core_news_md")

# Process a "long" text
texts = ["De deux choses l'une, ou le puits était vraiment bien profond, ou elle tombait bien doucement ; car elle eut tout le loisir, dans sa chute, de regarder autour d'elle et de se demander avec étonnement ce qu'elle allait devenir. D'abord elle regarda dans le fond du trou pour savoir où elle allait ; mais il y faisait bien trop sombre pour y rien voir. Ensuite elle porta les yeux sur les parois du puits, et s'aperçut qu'elles étaient garnies d'armoires et d'étagères ; çà et là, elle vit pendues à des clous des cartes géographiques et des images. En passant elle prit sur un rayon un pot de confiture portant cette étiquette, « MARMELADE D'ORANGES. » Mais, à son grand regret, le pot était vide : elle n'osait le laisser tomber dans la crainte de tuer quelqu'un ; aussi s'arrangea-t-elle de manière à le déposer en passant dans une des armoires. « Certes, » dit Alice, « après une chute pareille je ne me moquerai pas mal de dégringoler l'escalier ! Comme ils vont me trouver brave chez nous ! Je tomberais du haut des toits que je ne ferais pas entendre une plainte. » (Ce qui était bien probable.) Tombe, tombe, tombe ! « Cette chute n'en finira donc pas ! Je suis curieuse de savoir combien de milles j'ai déjà faits, » dit-elle tout haut. « Je dois être bien près du centre de la terre. Voyons donc, cela serait à quatre mille milles de profondeur, il me semble. » (Comme vous voyez, Alice avait appris pas mal de choses dans ses leçons ; et bien que ce ne fût pas là une très-bonne occasion de faire parade de son savoir, vu qu'il n'y avait point d'auditeur, cependant c'était un bon exercice que de répéter sa leçon.) « Oui, c'est bien à peu près cela ; mais alors à quel degré de latitude ou de longitude est-ce que je me trouve ? » (Alice n'avait pas la moindre idée de ce que voulait dire latitude ou longitude, mais ces grands mots lui paraissaient beaux et sonores.) Bientôt elle reprit : « Si j'allais traverser complétement la terre ? Comme ça serait drôle de se trouver au milieu de gens qui marchent la tête en bas. Aux Antipathies, je crois. » (Elle n'était pas fâchée cette fois qu'il n'y eût personne là pour l'entendre, car ce mot ne lui faisait pas l'effet d'être bien juste.) « Eh mais, j'aurai à leur demander le nom du pays. — Pardon, Madame, est-ce ici la Nouvelle-Zemble ou l'Australie ? » — En même temps elle essaya de faire la révérence. (Quelle idée ! Faire la révérence en l'air ! Dites-moi un peu, comment vous y prendriez-vous ?) « Quelle petite ignorante ! pensera la dame quand je lui ferai cette question. Non, il ne faut pas demander cela ; peut-être le verrai-je écrit quelque part. » Tombe, tombe, tombe ! — Donc Alice, faute d'avoir rien de mieux à faire, se remit à se parler : « Dinah remarquera mon absence ce soir, bien sûr. » (Dinah c'était son chat.) « Pourvu qu'on n'oublie pas de lui donner sa jatte de lait à l'heure du thé. Dinah, ma minette, que n'es-tu ici avec moi ? Il n'y a pas de souris dans les airs, j'en ai bien peur ; mais tu pourrais attraper une chauve-souris, et cela ressemble beaucoup à une souris, tu sais. Mais les chats mangent-ils les chauves-souris ? » Ici le sommeil commença à gagner Alice. Elle répétait, à moitié endormie : « Les chats mangent-ils les chauves-souris ? Les chats mangent-ils les chauves-souris ? » Et quelquefois : « Les chauves-souris mangent-elles les chats ? » Car vous comprenez bien que, puisqu'elle ne pouvait répondre ni à l'une ni à l'autre de ces questions, peu importait la manière de les poser. Elle s'assoupissait et commençait à rêver qu'elle se promenait tenant Dinah par la main, lui disant très-sérieusement : « Voyons, Dinah, dis-moi la vérité, as-tu jamais mangé des chauves-souris ? » Quand tout à coup, pouf ! la voilà étendue sur un tas de fagots et de feuilles sèches, — et elle a fini de tomber. Alice ne s'était pas fait le moindre mal. Vite elle se remet sur ses pieds et regarde en l'air ; mais tout est noir là-haut. Elle voit devant elle un long passage et le Lapin Blanc qui court à toutes jambes. Il n'y a pas un instant à perdre ; Alice part comme le vent et arrive tout juste à temps pour entendre le Lapin dire, tandis qu'il tourne le coin : « Par ma moustache et mes oreilles, comme il se fait tard ! » Elle n'en était plus qu'à deux pas : mais le coin tourné, le Lapin avait disparu. Elle se trouva alors dans une salle longue et basse, éclairée par une rangée de lampes pendues au plafond. Il y avait des portes tout autour de la salle : ces portes étaient toutes fermées, et, après avoir vainement tenté d'ouvrir celles du côté droit, puis celles du côté gauche, Alice se promena tristement au beau milieu de cette salle, se demandant comment elle en sortirait. Tout à coup elle rencontra sur son passage une petite table à trois pieds, en verre massif, et rien dessus qu'une toute petite clef d'or. Alice pensa aussitôt que ce pouvait être celle d'une des portes ; mais hélas ! soit que les serrures fussent trop grandes, soit que la clef fût trop petite, elle ne put toujours en ouvrir aucune. Cependant, ayant fait un second tour, elle aperçut un rideau placé très-bas et qu'elle n'avait pas vu d'abord ; par derrière se trouvait encore une petite porte à peu près quinze pouces de haut ; elle essaya la petite clef d'or à la serrure, et, à sa grande joie, il se trouva qu'elle y allait à merveille. Alice ouvrit la porte, et vit qu'elle conduisait dans un étroit passage à peine plus large qu'un trou à rat. Elle s'agenouilla, et, jetant les yeux le long du passage, découvrit le plus ravissant jardin du monde. Oh ! Qu'il lui tardait de sortir de cette salle ténébreuse et d'errer au milieu de ces carrés de fleurs brillantes, de ces fraîches fontaines ! Mais sa tête ne pouvait même pas passer par la porte. « Et quand même ma tête y passerait, » pensait Alice, « à quoi cela servirait-il sans mes épaules ? Oh ! que je voudrais donc avoir la faculté de me fermer comme un télescope ! Ça se pourrait peut-être, si je savais comment m'y prendre. » Il lui était déjà arrivé tant de choses extraordinaires, qu'Alice commençait à croire qu'il n'y en avait guère d'impossibles. Comme cela n'avançait à rien de passer son temps à attendre à la petite porte, elle retourna vers la table, espérant presque y trouver une autre clef, ou tout au moins quelque grimoire donnant les règles à suivre pour se fermer comme un télescope. Cette fois elle trouva sur la table une petite bouteille (qui certes n'était pas là tout à l'heure). Au cou de cette petite bouteille était attachée une étiquette en papier, avec ces mots « BUVEZ-MOI » admirablement imprimés en grosses lettres."]

# Beam configuration
beam_width = 16
beam_density = 0.0001

# For plots
x = []
y = []

# Treat the document multiple times
for i in range(0, 30):
    x.append(i)
    process = psutil.Process(os.getpid())
    y.append(process.memory_info().rss / 1000000)

    with nlp.disable_pipes('ner'):
        docs = list(nlp.pipe(texts))
    beams = nlp.entity.beam_parse(docs, beam_width=beam_width, beam_density=beam_density)

    for doc, beam in zip(docs, beams):
        entity_scores = defaultdict(float)
        for score, ents in nlp.entity.moves.get_beam_parses(beam):
            for start, end, label in ents:
                entity_scores[(start, end, label)] += score

# Give time for gc to do its work if needed
time.sleep(30)
x.append(x[-1]+1)
process = psutil.Process(os.getpid())
y.append(process.memory_info().rss / 1000000)

# Display memory usage evolution
plt.plot(x, y)
plt.show()

The result is a linear curve with a 250 Mb increase of memory usage that is never released (see attachment). Tested with thousands of documents, we eventually crashed our server.

mem_spacy

Another question comes with this bug :

  • Is there another way of obtaining confidence score for NER entities ?

Your Environment

  • Operating System: Windows-10-10.0.17134-SP0 and CentOS 7 (when packaged)
  • Python Version Used: 3.6.5
  • spaCy Version Used: 2.2.1 and 2.0.18
  • Environment Information: Windows environment is a dev environment. CentOS env is for deployment after we packaged the project. The first crash was produced on CentOS, and was reproduced on dev env after. The curve given above comes from a Windows environment.
@adrianeboyd adrianeboyd added bug Bugs and behaviour differing from documentation feat / ner Feature: Named Entity Recognizer perf / memory Performance: memory use labels Oct 11, 2019
@adrianeboyd
Copy link
Contributor

Thanks for the report and test case! Have you also seen the discussion in #3618? I suspect this is the same bug.

The current (obviously not very satisfactory) work-around is to periodically reload nlp(). See a few of the relevant comments:

Hopefully we'll be able to track this down soon...

@DDouteaux
Copy link
Author

Thanks for your quick answer !

I have already seen most of these posts, unfortunately :

  • I can not work without NER, so disabling it could not be done.
  • We already thought of reloading SpaCy model periodically. Hence, we restart our process every 10000 documents via an option of our webservice based on Gunicorn. Maybe we can lower this value, but then we fear to lose too many time waiting for models to be reloaded.
  • Using a pool can be done but then remains the fact that we will have to reload the model too much time.

For information, our current patch is to disable NER confidence computation, and we will re-wire it whenever a bug fix is released.

@adrianeboyd
Copy link
Contributor

adrianeboyd commented Oct 20, 2019

@honnibal: It might not be the whole story, but I think this is one spot with an obvious memory leak related to beam_parse:

cdef void* _init_state(Pool mem, int length, void* tokens) except NULL:
cdef StateC* st = new StateC(<const TokenC*>tokens, length)
return <void*>st

valgrind reports ~8MB lost per new StateC(), which is consistent with the 250MB / 30 iterations above.

It's called here and never deleted:

https:/explosion/thinc/blob/732b7c0366fd349e8131b6786130b74ffe063ab1/thinc/extra/search.pyx#L83-L86

@adrianeboyd
Copy link
Contributor

adrianeboyd commented Oct 21, 2019

Okay, so this is a separate issue from #3618 just related to beam_parse() where the beam states aren't being freed correctly. As far as I can tell, a fix will require changes to both thinc and spacy, which makes this a little more complicated, but I hope we'll have something ready soon. A quick preview of the updated memory usage:

4432-memory

@pramodith
Copy link

Hey, is this fix going to be relfected in the release of v2.2.4 or is it already in v2.2.3?

@adrianeboyd
Copy link
Contributor

Hi, this isn't in v2.2.3, sorry. It should be fixed in an upcoming release, but there isn't a concrete version number or release date set yet. If you need this in the meanwhile, you can compile the master branches from spacy and thinc from source, being sure to update the requirements first.

@lock
Copy link

lock bot commented Feb 22, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Feb 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Bugs and behaviour differing from documentation feat / ner Feature: Named Entity Recognizer perf / memory Performance: memory use
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants