google-deepmind / mujoco

Multi-Joint dynamics with Contact. A general purpose physics simulator.
https://mujoco.org
Apache License 2.0
8.3k stars 836 forks source link

Using `copy.deepcopy` to mjData seems to cause memory leaks #1572

Closed sck-robot closed 5 months ago

sck-robot commented 8 months ago

Hi,

I'm a student and I'm trying to use MuJoCo for my project.

I'm looking for some help with the deep copy of mjData struct.

Here is the minimal example to reproduce the problem:

import mujoco
import time
import copy

MODEL_XML = """
<?xml version="1.0" ?>
<mujoco>
  <asset> 
    <material name="body" rgba="0.8 0.6 .4 1"/>
    <texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
    <material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
  </asset>
    <worldbody>
        <geom name="floor" size="0 0 .05" type="plane" material="grid" condim="3"/>
        <body name="box" pos="0 0 1">
            <freejoint name="root"/>
            <geom size="0.15 0.15 0.15" type="box" material="body" />
            <inertial pos="0 0 0.02" mass="10" fullinertia="100000e-06   100000e-06   100000e-06   0 0 0"/>
        </body>
    </worldbody>
</mujoco>
"""

model = mujoco.MjModel.from_xml_string(MODEL_XML)
data = mujoco.MjData(model)

last_data = None
while data.time<10:

    # sim step
    mujoco.mj_step(model, data)

    print('Using shallow copy!')
    last_data = data

    # print('Using deep copy!')
    # last_data = copy.deepcopy(data)

    print('time:',round(last_data.time,3))
    time.sleep(0.005)

when using the shallow copy or only deep copy part of the mjData, the memory will not grow. However, if I use copy.deepcopy to mjData, the memory will gradually grow.

The following videos are recorded on my computer, the first one shows that memory remains unchanged after the program starts when using shallow copy, while the second one shows that memory grows when the program is running if I use copy.deepcopy.

https://github.com/google-deepmind/mujoco/assets/60764118/94b0bd8f-e8bc-4834-b468-057655537f8d

https://github.com/google-deepmind/mujoco/assets/60764118/5032a852-fc00-4e5f-95cd-72b999560902

It is worth noting that this problem does not exist in the version 2.3.7.

I'm not an expert in python and I'm not sure if this can be called memory leaks. Though I can deep copy part of mjData which I am interested in instead of deep copy the entire mjData, I am still curious about this since it may cause other problems.

Any ideas will be appreciated!

Operating system: Ubuntu 18.04.1 MuJoCo version: 3.1.3

dcheney01 commented 7 months ago

I have this same issue.

nimrod-gileadi commented 7 months ago

Note that in your example the "shallow copy" really does nothing, it just copies the reference to the same mjData object, so it's exactly the same as having last_data = data before the while loop and never assigning again.

nimrod-gileadi commented 7 months ago

I think this is related to issue #1518 where our conclusion was that C Python makes strange choices as to how to release memory.

If you are able to trigger an out-of-memory exception with this experiment, I'll look into it, otherwise I'll assume that it's just the same behaviour, and Python would eventually release that memory if there's enough memory pressure.

sck-robot commented 7 months ago

Hi Nimrod @nimrod-gileadi , thanks for your reply.

Actually Python won't release the memory if you run this code for longer (you can replace while data.time<10: with while True: in line 28), and eventually the memory usage will reach the limit and my computer will crash (It no longer responds to any commands).

The picture below is the result after running the code for a longer time, the memory usage is almost close to the upper limit. Here I have to stop the code to avoid computer crash. memory

I mentioned the impact of mujoco version in this issue before.

It is worth noting that this problem does not exist in the version 2.3.7.

I first found this problem on my server (mujoco version 3.1.3), while my personal computer (mujoco version 2.3.7) didn't have such problem. After I updated the version of mujoco (3.1.3), this problem also occurs on my personal computer. I test more versions of mujoco and found that this problem started to appear in mujoco version 3.0.1, and there was no such problem before mujoco version 3.0.1.

Although this problem does not currently affect my use of mujoco, it may be a hidden danger. I hope you can take some time to look into this issue, thank you very much!

nimrod-gileadi commented 5 months ago

Apologies for not looking into this deeper earlier. You are right, and I'm working on a fix now. Thanks for the detailed report.