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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scipy memory leak and unexpected fix with matplotlib #4678

Open
octavephotonics opened this issue Apr 9, 2024 · 0 comments
Open

Scipy memory leak and unexpected fix with matplotlib #4678

octavephotonics opened this issue Apr 9, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@octavephotonics
Copy link

馃悰 Bug

There appears to be a memory leak in the pyodide implementation of scipy.integrate that will lead to a numpy ArrayMemoryError after the integrator setup function is called multiple times. Interestingly, calling the unrelated add_subplot() function in matplotlib.figure after using the integrator apparently frees up the memory and allows subsequent calls to the integrator without errors.

The number of calls to the integrator before an error occurs depends on the size of the array to integrate and the type of integrator selected. I've been using the 'lsoda' integrator in scipy, but other implementations appear to have the same problem at larger array sizes. In the example below, the function can be called a total of four times before too much memory is used, and an error is thrown.

To Reproduce

You can see/run a minimal example to produce the error here:
https://pyscript.com/@nickburns/simulation-memory/latest

Pressing the 'Calculate' button in this example just runs the "simulation" function. With this configuration, it can be executed 4 times before more than 2GB of memory is allocated and an error results. Uncommenting the fig.add_subplot() line will allow everything to run an indefinite number of times.
image

from pyscript import document
import numpy as np
from scipy.integrate import complex_ode
import matplotlib.pyplot as plt

# Call this function multiple times in a row...
def handleButton(event):
    output = mysim()

    fig = plt.gcf()

    ## Comment the next line to see ArrayMemoryError after multiple calls to mysim()
    #fig.add_subplot(231)

def mysim():

    def rhs(z, aw): # a do-nothing function to allow setting up the integrator
        return aw
    
    # Up to 4 runs ok without fig.add_subplot call
    at = np.linspace(-2,2,2**12)
    r = complex_ode(rhs).set_integrator('lsoda', atol=1e-4, rtol=1e-4)

    # Up to 7 runs ok without fig.add_subplot call
    #at = np.linspace(-2,2,2**21)
    #r = complex_ode(rhs).set_integrator('dopri5', atol=1e-4, rtol=1e-4)
    
    r.set_initial_value(at) # this is where the memory gets allocated for the integrator
    
    # actually use the integrator in some code that would normally go here...
    return 'completed simulation'   

Expected behavior

Upon return of mysim() in the example above, memory allocated to the integrator should be freed as it is no longer in use, without needing to call the add_subplot function in matplotlib.

Environment

  • Pyodide Version 0.25.0
  • Pyscript 2024.3.2
  • Browser version: Edge 123.0.2420.65

Additional context

This code sequence works fine outside of pyodide.

@octavephotonics octavephotonics added the bug Something isn't working label Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant