From c5f7365d8a429da7dfc97c0674e62ac55d549144 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Oct 2017 16:50:15 +0200 Subject: [PATCH] Initial support of single GPU rendering when multiple cards with same name exists --- benchmark/configure.py | 56 +++++++++++++++++++++-------- benchmark/farm.py | 11 ++++++ benchmark/foundation/benchrunner.py | 4 +++ benchmark/foundation/context.py | 3 ++ benchmark/main.py | 5 +++ 5 files changed, 65 insertions(+), 14 deletions(-) diff --git a/benchmark/configure.py b/benchmark/configure.py index 80ead43..b9beefb 100644 --- a/benchmark/configure.py +++ b/benchmark/configure.py @@ -12,7 +12,11 @@ def isDisplayDevice(device): return "(Display)" in device.name -def setUseRequestedDevice(context, cpref, device_type, requested_device): +def setUseRequestedDevice(context, + cpref, + device_type, + requested_device, + device_single): import _cycles # Empty device type means we'l ltry to render on a single card, # preferably non-display one. @@ -22,7 +26,7 @@ def setUseRequestedDevice(context, cpref, device_type, requested_device): for device in cpref.devices: if isDisplayDevice(device): device.use = False - elif not device_found: + elif not device_found or not device_single: # Enable first non-display GPU. device_found = True device.use = True @@ -38,24 +42,35 @@ def setUseRequestedDevice(context, cpref, device_type, requested_device): for device in cpref.devices: device_name = device.name.replace(" (Display)", "") if device_name == requested_device: - device.use = True - device_found = True + if not device_found or not device_single: + device.use = True + device_found = True + else: + device.use = False else: device.use = False return device_found -def setDeviceCUDA(context, cpref, requested_device): +def setDeviceCUDA(context, cpref, requested_device, device_single): cpref.compute_device_type = 'CUDA' - return setUseRequestedDevice(context, cpref, 'CUDA', requested_device) + return setUseRequestedDevice(context, + cpref, + 'CUDA', + requested_device, + device_single) -def setDeviceOpenCL(context, cpref, requested_device): +def setDeviceOpenCL(context, cpref, requested_device, device_single): cpref.compute_device_type = 'OPENCL' - return setUseRequestedDevice(context, cpref, 'OPENCL', requested_device) + return setUseRequestedDevice(context, + cpref, + 'OPENCL', + requested_device, + device_single) -def setDeviceGPU(context, cpref, requested_device): +def setDeviceGPU(context, cpref, requested_device, device_single): import _cycles has_cuda = has_opencl = False for device in _cycles.available_devices(): @@ -65,9 +80,9 @@ def setDeviceGPU(context, cpref, requested_device): has_opencl = True if has_cuda: - return setDeviceCUDA(context, cpref, requested_device) + return setDeviceCUDA(context, cpref, requested_device, device_single) if has_opencl: - return setDeviceOpenCL(context, cpref, requested_device) + return setDeviceOpenCL(context, cpref, requested_device, device_single) return False @@ -121,6 +136,10 @@ def main(): parser.add_argument("--benchmark-device", help="Device to be rendered on", default="") + parser.add_argument("--benchmark-device-single", + help="Use single device when multiple are found", + action='store_true', + default=False) parser.add_argument("--benchmark-system-info", help="Dump whole system information", action='store_true', @@ -148,11 +167,20 @@ def main(): if args.benchmark_device_type == 'CPU': device_ok = setDeviceCPU(context, cpref) elif args.benchmark_device_type == 'CUDA': - device_ok = setDeviceCUDA(context, cpref, args.benchmark_device) + device_ok = setDeviceCUDA(context, + cpref, + args.benchmark_device, + args.benchmark_device_single) elif args.benchmark_device_type == 'OPENCL': - device_ok = setDeviceOpenCL(context, cpref, args.benchmark_device) + device_ok = setDeviceOpenCL(context, + cpref, + args.benchmark_device, + args.benchmark_device_single) elif args.benchmark_device_type == 'GPU': - device_ok = setDeviceGPU(context, cpref, args.benchmark_device) + device_ok = setDeviceGPU(context, + cpref, + args.benchmark_device, + args.benchmark_device_single) if not device_ok: sys.exit(1) diff --git a/benchmark/farm.py b/benchmark/farm.py index 628517f..b36f703 100755 --- a/benchmark/farm.py +++ b/benchmark/farm.py @@ -42,6 +42,10 @@ def configureArgumentParser(): parser.add_argument('-n', '--device-name', help="Device name to render on", default="") + parser.add_argument('-s', '--device-single', + help="Use single device when multiple matches", + action='store_true', + default=False) parser.add_argument('-v', '--verbose', help="Do verbose logging", action='store_true', @@ -66,6 +70,7 @@ def injectDefaultConfiguration(config): section = { "scenes_dir": os.path.join(root_dir, "scenes"), "device_name": "", + "device_single": "False", } config['farm'] = section @@ -83,6 +88,8 @@ def injectArgparseConfiguration(config, args): section['device_type'] = args.device_type if args.device_name: section['device_name'] = args.device_name + if args.device_single: + section['device_single'] = args.device_single def readConfiguration(args): @@ -323,6 +330,10 @@ def main(): ctx.scenes_dir = farm_config['scenes_dir'] ctx.device_type = farm_config['device_type'] ctx.device_name = farm_config['device_name'] + if farm_config['device_single'].lower() == "true": + ctx.device_single = True + else: + ctx.device_single = False ctx.image_output_dir = images_output_dir # Don't do any scenes when only querying for system information. if args.system_info: diff --git a/benchmark/foundation/benchrunner.py b/benchmark/foundation/benchrunner.py index adf057f..f1386bf 100644 --- a/benchmark/foundation/benchrunner.py +++ b/benchmark/foundation/benchrunner.py @@ -29,6 +29,8 @@ def constructBenchmarkCommand(ctx, scene, blendfile, output_folder, cfra): "--", "--benchmark-device-type", ctx.device_type]) if ctx.device_name: command.extend(["--benchmark-device", ctx.device_name]) + if ctx.device_single: + command.extend(["--benchmark-device-single"]) return command @@ -137,6 +139,8 @@ def benchmarkGetDeviceInfo(ctx): "--benchmark-device-type", ctx.device_type] if ctx.device_name: command.extend(["--benchmark-device", ctx.device_name]) + if ctx.device_single: + command.extend(["--benchmark-device-single"]) process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) diff --git a/benchmark/foundation/context.py b/benchmark/foundation/context.py index 4436529..ac9d973 100644 --- a/benchmark/foundation/context.py +++ b/benchmark/foundation/context.py @@ -7,6 +7,7 @@ class Context: __slots__ = ('blender', 'device_type', 'device_name', + 'device_single', 'scenes', 'scenes_dir', 'configure_script', @@ -19,6 +20,8 @@ class Context: self.device_type = 'CPU' # Name of the device to render on. self.device_name = 'NAME' + # Use single device when there are multiple one matching the name + self.device_single = False # By default we use empty list, it is up to the user to fill it in. self.scenes = [] # It is up to the user to provide proper path to scenes. diff --git a/benchmark/main.py b/benchmark/main.py index 25354f4..bf9bd79 100755 --- a/benchmark/main.py +++ b/benchmark/main.py @@ -32,6 +32,10 @@ def configureArgumentParser(): parser.add_argument('-n', '--device-name', help="Device name to render on", default="") + parser.add_argument('-s', '--device-single', + help="Use single device when multiple matches", + action='store_true', + default=False) parser.add_argument('-f', '--full-dump', help="Dump all available in formation", action='store_true', @@ -130,6 +134,7 @@ def main(): ctx.configure_script = args.configure_script ctx.device_type = args.device_type ctx.device_name = args.device_name + ctx.device_single = args.device_single if args.scenes: ctx.scenes = args.scenes else: