Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Memory Leak Caused by the circular reference. #559

Open
@zhi-bao

Description

@zhi-bao

First of all, thank you so much for developing such a powerful and interesting project.
We are a group working on libraries such asLIBSVM,LIBLINEAR,LibMultiLabel, and so on.
Recently, we have integratingpython-graphblas into our codebase to speed up sparse matrix operation.
However, during the integrations, we encountered a memory issue when using sparse matrix multiplication.
We would like to share our observation and findings, and hope to get some feedback on potential improvements.

The information about our sparse matrices and predefined variables is shown below:

weights shape: (135909, 826017)  # CSR and NNZ: 1,818,756,815instances shape: (153025, 135909)  # CSR and NNZ: 14,013,838batch_size = 256

Our usage is simplified in the following examples:

defpredict_values(A,B):C=gb.Matrix(float,A.shape[0],B.shape[1])C<<A.mxm(B,op=gb.semiring.min_plus)returnC.to_dense(fill_value=0)defmain():foridxinrange(0,instances.shape[0],batch_size):batch_x=instances[idx :idx+batch_size, :]results=predict_values(batch_x,weights)

We initially assumed that oncepredict_values returns and the local variableC goes out of thepredict_values function scope, its memory would be released (since the reference toC no longer exists).
However, based on our observations, the memory occupied byC is not released.
Instead, the memory usage grows linearly with each function call, until some conditions are met (i.e., the threshold of Python's garbage collector) and Python eventually release it.
This issue becomes more severe whenC consumes a large amount of memory.
IfC consumes a large amount of memory, this delayed release causes the system to consume all available memory (including swap), which in turn degrades the performance of matrix multiplication.
Upon investigation, we found that the reason of the memory issue comes from the circular reference in GraphBLAS.

classMatrix(BaseType):# SKIPdef__new__(cls,dtype=FP64,nrows=0,ncols=0,*,name=None):# SKIPifbackend=="suitesparse":self.ss=ss(self)

copied fromgraphblas/core/matrix.py

classss:__slots__="_parent","config"def__init__(self,parent):self._parent=parentself.config=MatrixConfig(parent)

copied fromgraphblas/core/ss/matrix.py.
The simplified reference structure is as follows:

Matrix M  └── .ss (attribute of M)         └── (references back to) M

This creates a circular reference between theMatrix object and its.ss attribute.
Since Python uses reference counting to manage memory, the reference count of objects involved in a circular reference never becomes zero, even when local variables go out of scope (e.g., our simplified example).
As a result, these objects remain in memory until Python's garbage collector detects and frees them.
However, the garbage collector does not detect them immediately.
In fact, it sets a threshold and uses it to decide when to detect and free those circular reference objects.
Therefore, if the threshold is not reached, the unreleased memory may gradually consume all available memory, which is consistent with our observations.

There are several ways to address this memory issue:

  • Callgc.collect() frequently to force the garbage collector to clean up circular references.
    However, this can introduce significant overhead and degrade performance.
  • Manually break the reference in the.ss attribute (e.g.,C.ss = None in our example) after the matrix is no longer needed. However, this is not a general or scalable solution, as it requires explicit intervention.
  • Replace the strong reference withweakref, which avoids reference cycles entirely.
    Would replacing the strong reference withweakref be a safe and effective solution in this case?

We were curious about the use of circular references inpython-graphblas, so we investigated it further.
Currently, we know that some functions in theMatrix class depend on the.ss attribute, and that thess object also needs to access information from theMatrix itself (e.g.,nrows andncols).
However, there might be alternative ways to support this interaction without the circular reference?!
That said, we may be missing some context. Is there a specific reason or design requirement for using this circular reference structure?

Is it possible to refactor this and improve this memory behavior inpython-graphblas?

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp