Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mata memory management

    Hi,

    i was wondering if there is any detailed documentation on how Mata manages memory, e.g. if I should think in terms of stack and heap-allocated memory.
    I particular, I realized that in my functions I often return pointers to locally declared/allocated matrices, which would be a mistake if this was C/C++ as the stack-based objects would be destroyed when the function terminates. In Mata, however, it seems to work.

    This, however, prompts the question when the memory of objects that have been allocated within a function is actually freed. This post [http://www.stata.com/statalist/archi.../msg00494.html ] suggests that setting a pointer to NULL actually triggers memory to be freed. For example, would this be enough to deallocate matrix m?

    Code:
    mata:
    mata clear
    
    pointer(real matrix) foo() {
    
        real matrix m
        m = J(10,10,0)
        
        return(&m)
    }
    
    m2 = foo()
    m2 = NULL
    
    end
    But then I wonder if Mata implements some sort of reference counting? After all, I could store more pointers to the same memory region in different places. So is a Mata pointer a "naked" C pointer or more like a C++ shared_ptr?

    Thanks for any comments!
    Richard

  • #2
    Mata handles memory management automatically. Mata objects, matrix, class, structure, etc, are reference counted and garbage collected. Setting a pointer to NULL will cause Mata to attempt to free the memory of the object being pointed to, but not necessarily memory will be freed if the object is referenced by other object.

    We can do an experiment with your code by using mata:mata memory to inspect the memory usage. First, we run the following:

    Code:
    cscript
    
    mata:
    pointer(real matrix) foo()
    {
        real matrix m
        
        m = J(10, 10, 0)
        return(&m)
    }
    
    m2 = foo()
    end
    mata:mata memory
    The output from mata:mata memory looks like

    Code:
    . mata:mata memory
                                     #              bytes
      ---------------------------------------------------
      autoloaded functions           0                  0
      ado functions                  0                  0
      defined functions              1                 96
    
      matrices & scalars             2                808
    
      overhead                                        168
      ---------------------------------------------------
      total                          3              1,072
    the "matrices & scalars" section reports 808 bytes used, which makes sense since a 10 by 10 matrix stores 10*10 doubles which uses 800 bytes (100*8 byes per double).

    Now we set m2 to NULL, in this case, since no other object is referencing the matrix which m2 points to, it causes the matrix to be freed.

    Code:
    mata: m2 = NULL
    mata:mata memory
    The output looks like:
    Code:
                                     #              bytes
      ---------------------------------------------------
      autoloaded functions           0                  0
      ado functions                  0                  0
      defined functions              1                 96
    
      matrices & scalars             1                  8
    
      overhead                                        112
      ---------------------------------------------------
      total                          2                216
    Now we repeat the above experiment, but this time, we create another pointer m3 to point to the same matrix which m2 points to:

    Code:
    mata:
    m2 = foo()
    m3 = m2
    mata memory
    m2 = NULL
    mata memory
    end
    The output looks like:

    Code:
    .
    . mata:
    ------------------------------------------------- mata (type end to exit) -----
    : m2 = foo()
    
    : m3 = m2
    
    : mata memory
                                     #              bytes
      ---------------------------------------------------
      autoloaded functions           0                  0
      ado functions                  0                  0
      defined functions              1                 96
    
      matrices & scalars             3                816
    
      overhead                                        224
      ---------------------------------------------------
      total                          4              1,136
    
    : m2 = NULL
    
    : mata memory
                                     #              bytes
      ---------------------------------------------------
      autoloaded functions           0                  0
      ado functions                  0                  0
      defined functions              1                 96
    
      matrices & scalars             3                816
    
      overhead                                        224
      ---------------------------------------------------
      total                          4              1,136
    
    : end
    Clearly this time, setting m2 to NULL does not free the underlying matrix since it is still referenced by m3. Now setting m3 to NULL as well will cause the matrix to be freed as expected.

    Code:
    .
    . mata:m3 = NULL
    
    . mata:mata memory
                                     #              bytes
      ---------------------------------------------------
      autoloaded functions           0                  0
      ado functions                  0                  0
      defined functions              1                 96
    
      matrices & scalars             2                 16
    
      overhead                                        168
      ---------------------------------------------------
      total                          3                280
    Last edited by Hua Peng (StataCorp); 09 Sep 2015, 23:47.

    Comment


    • #3
      Thanks for the clarification!

      Richard

      Comment

      Working...
      X