I've been looking into VRAM usage with adding and removing WorldObjects, here's some things that I found:
With a Qt canvas it seems like WorldObjects are garbage collected and GPU VRAM is freed only after mouse movements on the canvas even after the WorldObject has visibly been removed from the scene.
This example uses nvidia-smi:
- Creates a 4096x4096 image when you double click on the canvas.
- Click on the image to remove it from the scene and call
del on it. GPU VRAM is not freed.
- Make a mouse movement on the canvas after the image has been removed, GPU VRAM gets freed. But the GPU VRAM remains utilized until you make this mouse event.
import numpy as np
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx
import subprocess
canvas = WgpuCanvas()
renderer = gfx.WgpuRenderer(canvas)
scene = gfx.Scene()
camera = gfx.OrthographicCamera(5000, 5000)
camera.position.x = 2048
camera.position.y = 2048
def make_image():
data = np.random.rand(4096, 4096).astype(np.float32)
return gfx.Image(
gfx.Geometry(grid=gfx.Texture(data, dim=2)),
gfx.ImageBasicMaterial(clim=(0, 1)),
)
def draw():
renderer.render(scene, camera)
canvas.request_draw()
def print_nvidia(msg=""):
print(msg)
print(
subprocess.check_output(["nvidia-smi", "--format=csv", "--query-gpu=memory.used"]).decode().split("\n")[1]
)
print()
def add_img(*args):
print_nvidia("Before creating image")
img = make_image()
print_nvidia("After creating image")
scene.add(img)
img.add_event_handler(remove_img, "click")
draw()
print_nvidia("After add image to scene")
def remove_img(*args):
img = scene.children[0]
scene.remove(img)
draw()
print_nvidia("After remove image from scene")
del img
draw()
print_nvidia("After del image")
renderer.add_event_handler(print_nvidia, "pointer_move")
renderer.add_event_handler(add_img, "double_click")
draw()
run()
This outputs:
Before creating image
73 MiB
After creating image
73 MiB
After add image to scene
137 MiB
After remove image from scene
137 MiB
After del image
137 MiB
<pygfx.objects._events.PointerEvent object at 0x7fa186d8f970>
73 MiB
<pygfx.objects._events.PointerEvent object at 0x7fa186d8f5e0>
73 MiB
To follow up from #382 , with jupyter the situation is more messy. As Korijn mentioned here: #382 (comment)
If anyone runs into issues with jupyter in the future, in fastplotlib I'm working on a workaround where all WorldObjects are stored in a dict that fastplotlib uses internally, and only weakref proxies are used to access the WorldObject so that they are never directly exposed to any references on the jupyter side: fastplotlib/fastplotlib#160
I've been looking into VRAM usage with adding and removing WorldObjects, here's some things that I found:
With a Qt canvas it seems like WorldObjects are garbage collected and GPU VRAM is freed only after mouse movements on the canvas even after the WorldObject has visibly been removed from the scene.
This example uses
nvidia-smi:delon it. GPU VRAM is not freed.This outputs:
To follow up from #382 , with jupyter the situation is more messy. As Korijn mentioned here: #382 (comment)
If anyone runs into issues with jupyter in the future, in
fastplotlibI'm working on a workaround where allWorldObjectsare stored in a dict thatfastplotlibuses internally, and only weakref proxies are used to access theWorldObjectso that they are never directly exposed to any references on the jupyter side: fastplotlib/fastplotlib#160