I’m migrating BEVFormer (an auto-driving model training framework) from Py3.14 to 3.14t. Functionally it runs, but memory usage (RAM, not GPU memory) on 3.14t is about twice that of 3.14. I’ve run many training epochs and tried different GPUs; the issue reproduces reliably.
I traced it to BRC (biased ref count): when a non-owner thread decrefs and ob_ref_shared comes to 0, it has to have the owner thread read ob_ref_local and confirm the object can be collected. If the owner is detached, collection is delayed and the object sits in the BRC queue.
In torch.DataLoader this case is common: owner threads stay detached for a long time, tied to how multiprocessing.Queue is implemented. A repro is here.
import gc, os, re, sys, time
import torch, torch.multiprocessing as mp
HDR = re.compile(r"^[0-9a-f]+-[0-9a-f]+ ")
NB = 64 * 1024 * 1024
# count mem usage
def mb():
tot, path = 0.0, ""
for l in open("/proc/self/smaps"):
if HDR.match(l):
f = l.split(); path = f[5] if len(f) > 5 else ""
elif l.startswith("Size:") and path.startswith("/dev/shm/torch"):
tot += int(l.split()[1]) / 1024
return tot
def consumer(q):
while True:
x = q.get()
if x is None:
break
del x
if __name__ == "__main__":
q = mp.Queue()
p = mp.Process(target=consumer, args=(q,))
p.start()
gc.collect(); gc.disable()
t = torch.empty(NB)
q.put(t)
del t
time.sleep(1)
[None for _ in range(3 * 10**7)] # spin
print(f" GIL={sys._is_gil_enabled()} {mb():5.0f} MB", flush=True)
q.put(None)
p.join()
How should this be fixed? The most direct approach is to change torch.DataLoader or multiprocessing.Queue so the owner does not stay detached. I tried that; it needs a lot of code changes and didn’t work well.
Another way is to change BRC in CPython so a non-owner can move the owner from detached to suspended (similar to STW), read ob_ref_local, decide whether the object can be collected, then put the owner back from suspended to detached. That sounds quite unsafe, but it worked: on BEVFormer again, 3.14t memory matched 3.14.
Is there a better way to handle this? I can post my BRC patch; it was written on 3.14, not current main.