home/ atoms/ multiprocess-generation-viewer

Separating image generation and display into different OS processes prevents Python's GIL from throttling GPU throughput

Python’s Global Interpreter Lock (GIL) prevents two threads from running Python bytecode simultaneously. In a naive implementation, a tkinter or pygame display loop sharing a thread with the GPU inference loop would serialise them. StreamDiffusion’s examples spawn separate OS processes using multiprocessing.get_context('spawn'): one process owns the CUDA context and runs the inference loop, another owns the display (tkinter/OpenCV). Data crosses the process boundary via multiprocessing.Queue. block=False on queue.put() means the inference process never stalls waiting for the display to consume frames; frames are dropped instead of blocking GPU utilisation.

Examples

ctx = get_context('spawn')       # CUDA-safe on all platforms
queue = ctx.Queue()
process1 = ctx.Process(target=image_generation_process, args=(queue, ...))
process2 = ctx.Process(target=receive_images, args=(queue, ...))
process1.start(); process2.start()

Assessment

Why is get_context('spawn') preferred over get_context('fork') for CUDA workloads? What would go wrong if the CUDA context were forked rather than freshly initialised in the child process?

“process1 = ctx.Process( target=image_generation_process”
corpus · streamdiffusion-pipeline-for-real-time-interactive-image-gen · chunk 33