Getting Blender to use CUDA in a render farm

In an earlier article I covered how I got the NVIDIA Tesla K10 GPU cards working under Ubuntu 20.04 with CUDA. In this article I will cover how I got Blender working to allow me to use them.

As a reminder I have a pair of ASUS ESC 4000 2U servers, each dual 8 core Xeon (32 CPU threads), 64GB of system memory & each containing 4 NVIDIA Tesla K10 GPU cards. Each GPU card contains 2 GPUS with 4GB of memory each, totalling 8 GPUS & 32GB of memory just for graphics.

Note: The very first time you run Blender it will compile the CUDA driver it needs. This will take a few minutes before it can do any rendering.

Now Blender has all of it’s config within each individual .blend file, so you have to set it up to use GPU’s within the UI – which isn’t possible on a headless system installed in a rack.

To get around this we have the .blend file configured to use just the CPU & we then use a pair of shell and Python wrappers to use the GPU’s.

Firs the shell script. This one renders the first frame in the .blend file:

#!/bin/sh

RENDER_DIR=$(pwd)/render

mkdir -p ${RENDER_DIR}

blender -b intro.blend \
	-o ${RENDER_DIR}/frame_##### -F PNG -x 1 \
	-P gpurender.py \
	-E CYCLES \
	-t 0 \
	-f 1 \
	-- \
	--cycles-device CUDA \
	--cycles-print-stats

Here it’s set to render the first frame (-f 1) from the file intro.blend.

It will render the frame into the render directory (which it will create) as a png image. This is setup with the -o and -F parameters.

The other parameters tell it to use the CYCLES render engine and the -P refers to a python script. This script tells blender to use the GPU’s:

import bpy

bpy.data.scenes[0].render.engine = "CYCLES"

# Set the device_type
bpy.context.preferences.addons[
    "cycles"
].preferences.compute_device_type = "CUDA"

# Set the device and feature set
bpy.context.scene.cycles.device = "GPU"

# get_devices() to let Blender detects GPU device
bpy.context.preferences.addons["cycles"].preferences.get_devices()
print(bpy.context.preferences.addons["cycles"].preferences.compute_device_type)
for d in bpy.context.preferences.addons["cycles"].preferences.devices:
    d["use"] = 0
    if d["name"][:6] == 'NVIDIA':
        d["use"] = 1
    print(d["name"], d["use"])

What the script does is ensures the scene uses CYCLES, then selects all NVIDIA GPU’s for rendering but disables the use of the CPU.

When run you should then see the frame being rendered, something like the following:

Blender rendering a single frame using GPU’s

If you have installed nvtop you can also see the GPU’s in action during the render:

Now the python script works if the .blend file has a single scene. It could be reworked to support multiple scenes but for now it does what I need.

To render the entire animation in one go you just need to change the shell script from rendering a single frame (-f 1) to all frames (-a):

#!/bin/sh

RENDER_DIR=$(pwd)/render

mkdir -p ${RENDER_DIR}

blender -b intro.blend \
	-o ${RENDER_DIR}/frame_##### -F PNG -x 1 \
	-P gpurender.py \
	-E CYCLES \
	-t 0 \
	-a \
	-- \
	--cycles-device CUDA \
	--cycles-print-stats

Just make certain that the render directory is empty, run that script & come back in a few hours. Once done you should see that directory full of png images, one per frame, ready to be formed into an animation.

Author: petermount1

Prolific Open Source developer who also works in the online gaming industry during the day. Develops in Java, Go, Python & any other language as necessary. Still develops on retro machines like BBC Micro & Amiga A1200

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s