ToCPU
For when the GPU isn't the right tool for the job
- image
- IMAGE
The name is a slight lie. ToCPU doesn't tell any node to run on your CPU - it just takes an image tensor that's sitting in VRAM and moves it to system RAM. That's the entire node: one IMAGE in, one IMAGE out, zero settings. It's one half of the tiny ComfyUI-ToDevice pack, and despite the modest frame, it fixes one of the most annoying errors you can hit with community workflows.
The failure mode it exists for
ComfyUI normally puts image tensors wherever the model is, and that's the GPU - for good reason. But a specific category of nodes doesn't want CUDA tensors. Anything doing its image math in numpy or OpenCV - certain masks, image-processing, and video-frame utilities - quietly expects a CPU tensor. Hand it a tensor on cuda:0 and you get the signature error most beginners meet sooner or later:
can't convert cuda:0 device type tensor to numpy
That's the "please stop being on the GPU" tantrum. ToCPU is the polite answer. You wire it in front of the node that's choking, it hands over a CPU tensor, the node runs happily, and then you usually send the image back to the GPU with the pack's other node, ToGPU, so the rest of the graph - sampler, VAE, preview - is back on the accelerator where it belongs.
How it works
The implementation is a single PyTorch call:
return (image.cpu(),)
That's it. The required image input is your IMAGE tensor; the output is the same tensor now living in system RAM. No optional inputs, no modes, no list handling. If the tensor is already on CPU, .cpu() returns it untouched, so you don't pay for a pointless copy.
Inputs and outputs that matter
There's exactly one of each, so this is the rare node where the list is the whole story:
- image (required,
IMAGE) - the tensor you want off the GPU - IMAGE (output) - the same tensor on CPU, wired into whatever node was complaining
Worth knowing before you wire it in: this only handles IMAGE. It won't move latents, masks, or models, and it can't force a node that hardcodes CUDA internally to suddenly behave - it only changes what the tensor looks like when it arrives.
Install
The README's documented path is a plain clone, and that's genuinely all it needs. There's no requirements.txt, no model files, no heavy dependencies - just the torch that ComfyUI already has.
cd ComfyUI/custom_nodes
git clone https://github.com/Noma-Machiko/ComfyUI-ToDevice.git
Restart ComfyUI and the nodes appear under utils. If you're on ComfyUI Manager, searching "ToDevice" usually turns the pack up as well.
Gotchas
- Use it as a boundary, not a lifestyle. Shuffling tensors between VRAM and system RAM crosses the PCIe bus, which is roughly 11x slower than GPU memory bandwidth. The community consensus is blunt: "the performance penalty for shuffling memory from VRAM to RAM is so huge that it makes it usually not worth it." One ToCPU at the edge of a CPU-only node is correct. Wrapping big parts of your graph in CPU→GPU shuttles is how you turn a fast workflow into a slide show.
- It can't override a node's internals. If a node moves its own data back to CUDA regardless of what you feed it, ToCPU won't stop the crash - it only changes the tensor you hand over.
- Nothing else ships with it. No batch extras, no upscaling, no hidden features. Two nodes, one trick, done.
Bottom line: keep this one in your back pocket for the day a workflow errors on device mismatch. It's the fix you'll forget about until you need it, and then it's the fix you can't believe didn't ship with ComfyUI.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |