Initial commit
This commit is contained in:
162
benchmark/foundation/benchrunner.py
Normal file
162
benchmark/foundation/benchrunner.py
Normal file
@@ -0,0 +1,162 @@
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
from foundation import (logger,
|
||||
progress,
|
||||
stats,
|
||||
util)
|
||||
|
||||
|
||||
def constructBenchmarkCommand(ctx, scene, blendfile, output_folder, cfra):
|
||||
command = [ctx.blender,
|
||||
"--background",
|
||||
"--factory-startup",
|
||||
"-noaudio",
|
||||
"--debug-cycles",
|
||||
"--enable-autoexec",
|
||||
"--engine", "CYCLES",
|
||||
blendfile]
|
||||
if ctx.image_output_dir:
|
||||
output = os.path.join(ctx.image_output_dir, scene) + "#"
|
||||
command.extend(["--render-format", "PNG",
|
||||
"--render-output", output])
|
||||
else:
|
||||
command.extend(["--render-output", output_folder,
|
||||
"--render-format", "PNG"])
|
||||
command.extend(["--python", ctx.configure_script,
|
||||
"-f", str(cfra),
|
||||
"--", "--benchmark-device-type", ctx.device_type])
|
||||
if ctx.device_name:
|
||||
command.extend(["--benchmark-device", ctx.device_name])
|
||||
return command
|
||||
|
||||
|
||||
def benchmarkBlenderWatched(command):
|
||||
# Run Blender with configured command line.
|
||||
logger.DEBUG("About to execuet command: {}" . format(command))
|
||||
start_time = time.time()
|
||||
process = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
# Keep reading status while Blender is alive.
|
||||
st = stats.Stats()
|
||||
while True:
|
||||
line = process.stdout.readline()
|
||||
if line == b"" and process.poll() is not None:
|
||||
break
|
||||
line = line.decode().strip()
|
||||
if line == "":
|
||||
continue
|
||||
if logger.VERBOSE:
|
||||
print(line)
|
||||
else:
|
||||
logger.DEBUG("Line from stdout: {}" . format(line))
|
||||
st.update(line)
|
||||
if st.current_tiles != 0:
|
||||
elapsed_time = time.time() - start_time
|
||||
elapsed_time_str = util.humanReadableTimeDifference(elapsed_time)
|
||||
progress.progress(st.current_tiles,
|
||||
st.total_tiles,
|
||||
prefix="Path Tracing Tiles {}" .
|
||||
format(elapsed_time_str))
|
||||
|
||||
# Clear line used by progress.
|
||||
progress.progressClear()
|
||||
|
||||
if process.returncode != 0:
|
||||
logger.ERROR("Rendering crashed")
|
||||
return None
|
||||
logger.OK("Successfully rendered")
|
||||
|
||||
return st
|
||||
|
||||
|
||||
def benchmarkScene(ctx, scene):
|
||||
logger.BOLD("Begin benchmark of scene {}" . format(scene))
|
||||
# Get usable full path to the corresponding .blend file.
|
||||
blendfile = ctx.getSceneFilename(scene)
|
||||
logger.DEBUG("File to use: {}" . format(blendfile))
|
||||
# Get command for rendering.
|
||||
# TODO(sergey): Create some temp folder.
|
||||
cfra = util.queryCurrentFrame(blendfile)
|
||||
command = constructBenchmarkCommand(ctx, scene, blendfile, "/tmp/", cfra)
|
||||
logger.DEBUG("Command for rendering: {}" . format(command))
|
||||
|
||||
logger.INFO("> Warm-up round, making sure everything is ready " +
|
||||
"(this might take several minutes).")
|
||||
warmup_command = command + ['--benchmark-warmup']
|
||||
benchmarkBlenderWatched(warmup_command)
|
||||
# Remove resutl of warmup round.
|
||||
if ctx.image_output_dir:
|
||||
full_image_output = os.path.join(ctx.image_output_dir, scene) + \
|
||||
str(cfra) + ".png"
|
||||
if os.path.exists(full_image_output):
|
||||
os.remove(full_image_output)
|
||||
# TODO(sergey): Consider doing several passes.
|
||||
logger.INFO("> Doing real benchmark pass now.")
|
||||
stats = benchmarkBlenderWatched(command)
|
||||
# Rename file to more sensible name.
|
||||
if ctx.image_output_dir:
|
||||
if os.path.exists(full_image_output):
|
||||
full_image_output_no_frame = \
|
||||
os.path.join(ctx.image_output_dir, scene) + ".png"
|
||||
os.rename(full_image_output, full_image_output_no_frame)
|
||||
if stats:
|
||||
logger.INFO("Total render time: {}" . format(
|
||||
util.humanReadableTimeDifference(
|
||||
stats.pipeline_render_time)))
|
||||
return stats
|
||||
|
||||
|
||||
def benchmarkAll(ctx):
|
||||
"""
|
||||
Benchmark all scenes from the cntext with requested settings.
|
||||
"""
|
||||
# First of all, print summary of what we'll be doing.
|
||||
ctx.printSummary()
|
||||
if not ctx.verify():
|
||||
return False
|
||||
all_stats = {}
|
||||
for scene in ctx.scenes:
|
||||
file_stats = benchmarkScene(ctx, scene)
|
||||
all_stats[scene] = file_stats
|
||||
return all_stats
|
||||
|
||||
|
||||
def benchmarkGetDeviceInfo(ctx):
|
||||
command = [ctx.blender,
|
||||
"--background",
|
||||
"--factory-startup",
|
||||
"-noaudio",
|
||||
"--enable-autoexec",
|
||||
"--engine", "CYCLES",
|
||||
"--python", ctx.configure_script,
|
||||
"--",
|
||||
"--benchmark-device-type", ctx.device_type]
|
||||
if ctx.device_name:
|
||||
command.extend(["--benchmark-device", ctx.device_name])
|
||||
process = subprocess.Popen(command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
stdout, stderr = process.communicate()
|
||||
lines = stdout.decode().split("\n")
|
||||
# Parse output
|
||||
device_type = ""
|
||||
compute_devices = []
|
||||
for line in lines:
|
||||
if line.startswith("Compute device type:"):
|
||||
device_type = line.split(':', 1)[1].strip()
|
||||
elif line.startswith("Using compute device:"):
|
||||
compute_devices.append(line.split(':', 1)[1].strip())
|
||||
return {"device_type": device_type,
|
||||
"compute_devices": compute_devices}
|
||||
|
||||
|
||||
def benchmarkPrintDeviceInfo(ctx):
|
||||
device_info = benchmarkGetDeviceInfo(ctx)
|
||||
logger.INFO(" Device type: {}" . format(device_info["device_type"]))
|
||||
logger.INFO(" Compute devices:")
|
||||
for compute_device in device_info["compute_devices"]:
|
||||
logger.INFO(" {}" . format(compute_device))
|
Reference in New Issue
Block a user