-
Notifications
You must be signed in to change notification settings - Fork 0
/
run_benchmark.py
107 lines (89 loc) · 4.17 KB
/
run_benchmark.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import argparse
from dataclasses import dataclass
import urllib.request
import zipfile
import os
import shutil
import subprocess
import csv
import io
''' Script to run blender benchmarks. It will download files the first time
run with python3 run_benchmark.py PATH_TO_BLENDER_EXE OUT_CSV.csv
use --help for options
'''
@dataclass
class Test:
''' Handles getting data and running test '''
name: str
archive_url: str
blend_file: str
frame_num: int
settings: dict # settings to set before running file
command_options: list
def get_archive(self):
if os.path.exists(os.path.join('scenes', self.name)):
print('Archive', self.name, 'Exists already')
else:
print('Getting archive', self.name, self.archive_url)
urllib.request.urlretrieve(self.archive_url, "archive.zip")
with zipfile.ZipFile("archive.zip", 'r') as zip_ref:
zip_ref.extractall(os.path.join('scenes', self.name))
print('Extracted to', self.name)
os.remove("archive.zip")
def run_test(self, blender_exe, render_backend, tile_size=64, device_options=[]):
blend_file = os.path.join('scenes', self.name, self.blend_file)
renderer = render_backend if render_backend == 'RPR' else 'CYCLES'
set_backend = None
if renderer == 'CYCLES':
set_backend = f"import bpy; bpy.context.preferences.addons['CYCLES'].preferences.compute_device_type = {render_backend}; bpy.context.scene.render.tile_x = {tile_size}; bpy.context.scene.render.tile_y = {tile_size};"
cmd = [blender_exe, '-b', blend_file, '-E', renderer, '-f', str(self.frame_num)]
if set_backend:
cmd += ['--python-expr', set_backend]
cmd += self.command_options
print('Running', cmd)
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# parse stdout
time = ''
max_mem = ''
started, ended = False, False
bvh_time = ''
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
tokens = line.split('|')
if not len(tokens) > 1:
continue
if "Time:" in tokens[1]:
time = tokens[1].split('Time:')[1]
if not started and 'Remaining' in tokens[2]:
started = True
bvh_time = time
elif started and not ended and 'Remaining' not in tokens[2]:
ended = True
max_mem = tokens[2].split(':')[2]
print('Done rendering', self.blend_file)
return {'Test Name':self.name,
'Render Time': time,
'Peak Memory': max_mem,
'BVH Time': bvh_time}
# rendering backends
ACCEPTED_BACKENDS = ('OPENCL', 'CPU', 'RPR', 'OPTIX', 'CUDA')
# list of tests to do
TESTS = [
Test('BMW', 'https://download.blender.org/demo/test/BMW27_2.blend.zip', 'bmw27/bmw27_gpu.blend', 1, {}, []),
Test('Classroom', 'https://download.blender.org/demo/test/classroom.zip', 'classroom/classroom.blend', 1, {}, []),
Test('Pavillion', 'https://download.blender.org/demo/test/pabellon_barcelona_v1.scene_.zip', 'pabellon_barcelona_v1.scene_/3d/pavillon_barcelone_v1.2.blend', 1, {}, []),
]
RESULT_COLUMNS = ['Test Name', 'Render Time', 'Peak Memory', 'BVH Time']
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('blender_exe', help="Path to blender executable")
parser.add_argument('-backend', metavar='-b', default='OpenCL', choices=ACCEPTED_BACKENDS, help="Rendering backend to use, choices " + str(ACCEPTED_BACKENDS))
parser.add_argument('-gpu_statees', metavar='-gpus', default='1', help='Comma separated list of devices to use. CPU is 0')
parser.add_argument('-tile_size', default=64, help="Tile size for Cycles renders")
parser.add_argument('output', help='Output CSV file')
args = parser.parse_args()
with open(args.output, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=RESULT_COLUMNS)
writer.writeheader()
for test in TESTS:
test.get_archive()
writer.writerow(test.run_test(args.blender_exe, args.backend, args.tile_size))