Задать параллельный запуск подпроцесса Python
Задача, сделать несколько рендеров параллельно. Из инструментов Python и Blender.
Есть скрипт, который запускает рендер Blender через консоль один за другим. Один рендер длиться приблизительно 1 минуту. Этот скрипт можно свести сейчас к двум строкам:
sh = ['blender', "-b", 'file.blend', "-P", 'script.py')]
proc = subprocess.run(sh)
Где script.py это файл где хранятся настройки сцены для одного рендера.
Так как рендеринг это довольно затратное дело, то я хочу запустить скрипт в отдельном процессе, по этому использую библиотеку multiprocessing. В итоге код стал выглядеть примерно так:
procs = []
for num in range(len(camera_points)):
sh = ['blender', "-b", 'file.blend', "-P", f'script_{num}.py')]
proc = Process(target=subprocess.run, args=(sh,))
procs.append(proc)
proc.start()
for proc in procs:
proc.join()
После того как я получу рендеры, я хочу их загрузить на s3 bucket, по этому я жду окончания этих процессов.
Я ожидал получить прирост скорости хотя бы в х4, так как теперь вместо одного рендера на одну минуту, будет проходить условно 5 рендеров за одну минуту. Однако в реальности 5 процессов запустились одновременно, один за другим записали результат в папку и суммарное время выполнение, составило 5 минут. В то время когда я ожидал что время выполнения сократиться хотя бы до 2.
Рендеринг проводился на AWS на сервере g3.16xlarge, с установленными и активированными драйверами GRID. В процессе рендеринга, половина GPU большую часть времени простаивала.
Ответы (1 шт):
Не надо запускать процессы по числу кадров. Они конкурируют за ресурсы которых явно меньше чем нужно. multiprocessing.Pool запустит несколько процессов и распределит кадры между ними:
import multiprocessing
import subprocess
def render(num):
print('start', num)
subprocess.run(['blender', '-b', 'file.blend', "-P", f'script_{num}.py'])
print('stop', num)
if __name__ == '__main__':
n_cameras = 100
with multiprocessing.Pool() as p:
p.map(render, range(n_cameras))
print('done')