_cycles.available_devices now has a mystery argument?

Hi, today I found that _cycles.available_devices() requires an argument. As far as I know this has happened since 2.80.40. But there’s no information as to what this argument is supposed to be. I’ve managed to find out through trial and error that is required to be a string.

However, other than that, I don’t know anything else. The method seems to work fine if I use a blank string, so “” as the input like this;

_cycles.available_devices("")

This seems to return the correct results. But I am wary that this may only work in certain situations, please can someone shed light on thiis change and what the new argument should be.

Thanks!

1 Like

As per Python convention, any modules or functions with _ prefix are a private API. We can change them at any time, so I do not recommend using them in add-ons.

The argument can be “CPU”, “CUDA” or “OPENCL” to get only the devices of a specific type. “” gives you all devices.

Thanks @brecht, just out of curiosity, is there a public part of the API that can give us all devices? It has to work in background mode, that’s the only potentially complicating issue

There is:

cycles_preferences = context.preferences.addons['cycles'].preferences
cuda_devices, opencl_devices = cycles_preferences.get_devices()

Ok, I recall that didn’t work for us for some reason, but will try again since that was 2.79 and now we’re in 2.80 land. If it don’t work, have you knowledge of any changes for the _cycles module I should be wary of?

A lot of things changed regarding scene export and handling of render passes, but I would hope you’re not using those internal functions.

Ha… of course not… not yet @brecht :expressionless: but some day soon, when you least expect it

I might

Hi @brecht As I recalled, the method you mention above using preferences doesn’t work in background, this is the output I get.

jimbosmaccypro:MacOS jamescrowther$ ./blender -b --python-console
Read prefs: /Users/jamescrowther/Library/Application Support/Blender/2.79/config/userpref.blend found bundled python: /Applications/Blender/blender.app/Contents/Resources/2.79/python
HEY! My script registered
Python 3.5.3 (default, May 29 2017, 11:05:36) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

>>> import bpy
>>> bpy.context.user_preferences
<bpy_struct, UserPreferences at 0x107220e98>
>>> bpy.context.user_preferences.addons['cycles'].preferences.get_devices()
([], [])

However the following seems to work just fine:

>>> import _cycles
>>> _cycles.available_devices()
(('Intel Core i5-5257U CPU @ 2.70GHz', 'CPU', 'CPU'),)
>>> 

The above was done using 2.79b in background mode. So it seems the public part of the API for looking at what devices cycles has recognised, doesn’t work as desired. This is what I referred to above when I mentioned that we’d decided to use the private api since the public one did not do what we thought it would according to the API docs when running blender in background mode.

We run servers for rendering on various hardware, a lot of which, in the case of the cloud, has no monitor attached and so we run the processes in background mode. Therefore we really need something that works in background mode. Is it intentional that the public API method you showed me above does not work in background mode?

The code above works for me in latest Blender 2.80. Also, the devices are returned correctly when using Blender as a Python module. I do recall having the exact same issue as you with 2.79, but that seems to be fixed. I’ve tested this on Linux here.

Cool, I’ll try with 2.80.

Ok, I get the following in 2.80.44, build hash 3d16a268ee68, guessing this is in the new API cause the objects returned used to be tuples containing string constants, now we get CyclesDeviceSettings?

jimbosmaccypro:MacOS jamescrowther$ ./blender -b --python-console
Read prefs: /Users/jamescrowther/Library/ApplicationSupport/Blender/2.80/config/userpref.blend
found bundled python: /Users/jamescrowther/Downloads/blender-2.80.0-git20190208.3d16a268ee68-x86_64/blender.app/Contents/Resources/2.80/python
Warning: class DebuggerAddonPreferences contains a properties which should be an annotation!
/Users/jamescrowther/Library/Application Support/Blender/2.80/scripts/addons/remote_debugger.py:116
make annotation: DebuggerAddonPreferences.eggpath
make annotation: DebuggerAddonPreferences.pydevpath
Python 3.7.0 (default, Sep 11 2018, 17:36:20) 
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import bpy
>>> bpy.context.preferences.addons['cycles'].preferences.get_devices()
([<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>],     [<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>])
>>> _
([<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>],      [<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>])
>>> _[0]
[<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>]
>>> _
[<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>]
>>> _[0]
<bpy_struct, CyclesDeviceSettings("Intel Core i5-5257U CPU @ 2.70GHz")>
>>> dir(_)
['__annotations__', '__dict__', '__doc__', '__module__', '__weakref__', 'bl_rna', 'id', 'name', 'rna_type', 'type', 'use']
>>> bpy.app.build_hash
b'3d16a268ee68'
>>> bpy.app.version
(2, 80, 44)

That observation is correct. With such a CyclesDeviceSettings object it is convenient to turn features on or query what type they are.

On my system, I can grab the device settings for my GPU like this:

x = bpy.context.preferences.addons.get('cycles').preferences.get_devices()[0][0]

Then I can enable it for rendering using:

x.use = True

I can also query a few things from it:

x.use   # true if enabled for rendering
x.type  # 'CUDA' or 'CPU' (or maybe 'OPENCL' on AMD systems, can not test that however)
x.id    # 'CUDA_GeForce GT 650M_0000:01:00'
x.name  # 'GeForce GT 650M (Display)'

However I have not tried yet to set x.use = True and render a scene directly afterwards yet.

@brecht Ok, in 2.80 the way you described above:

cycles_preferences = context.preferences.addons['cycles'].preferences
cuda_devices, opencl_devices = cycles_preferences.get_devices()

does work. However, I can’t find CyclesDeviceSettings in the API. It seems simple enough from looking at its attributes, but would be nice to know when we’ll see it documented, any ideas when that might be?