Hey all,
Some time ago I got frustrated by the render time so I played a little with multiprocessing. I switched from Drawbot to Processing I wanted to share this code with you guys. Just came across it and figured to share.
Now, don't ask me what does what, since I don't remember :)
But I'm sure this will help some people with some long renders. You can render multiple frames a once, so no multiprocessing on one frame.
# main.py
import threading
from queue import Queue
import multiprocessing
import datetime
import time
import drawBot
#
import settings as set
def run(args):
frame = args#[0]
print("frame: ", frame)
drawBot.newDrawing() # start from scratch, no multipage
drawBot.newPage(set.canvasWidth, set.canvasHeight)
time = frame / set.frames
# teken een achtergrond
drawBot.fill(1) # wit
drawBot.rect(0, 0, set.canvasWidth, set.canvasHeight)
drawBot.fill(0) # zwart
angle = drawBot.radians(360 * time)
x = set.canvasWidth / 2 + 100 * drawBot.sin(angle)
drawBot.oval(x - 100, 200, 200, 200)
drawBot.saveImage(set.pathExport + set.exportFileName + str(frame) + "." + set.exportFileType)
for i in range(20):
frame = frame * frame
def threader():
while True:
worker = q.get()
run([ worker ])
q.task_done()
q = Queue()
def main_tr():
for x in range(10):
t = threading.Thread(target=threader)
t.daemon = True
t.start()
start = time.time()
for worker in range(100):
q.put(worker)
q.join()
print('total time', time.time() - start)
def main_pool():
multiprocessing.set_start_method('spawn')
p = multiprocessing.Pool( processes = (multiprocessing.cpu_count()-1))
p.map(run, range(set.frames))
p.close
def main_mp():
processes = multiprocessing.cpu_count()
print( 'utilizing %d cores\n' % processes )
ctx = multiprocessing.get_context('spawn')
processes = []
queue = ctx.Queue() # what does this do? :) :)
for frame in range(set.frames):
processes.append(ctx.Process(target=run, args=([ frame ], )))
for p in processes:
p.start()
for p in processes:
p.join()
# for _ in range(times): # I've commented this one out. It works without. But what does it do? :) :)
# assert queue.get(), "One of processes failed."
def main():
for frame in range(set.frames):
run( [ frame ] )
if __name__ == '__main__':
startTime = datetime.datetime.now()
#main_mp() # multiprocessing 1 #10.5
#main_tr() # multithreading
main_pool() #4.55
#main() # default serial # 15.65
print(datetime.datetime.now() - startTime)
print("--End--")
# settings.py
canvasWidth = 500
canvasHeight = 500
fps = 5
seconds = 10
duration = 1 / fps
frames = seconds * fps
pathExport = '___export/'
exportFileName = "export_"
exportFileType = "gif"
Stich it all back together as one gif:
export_gif.py
import settings as set
def exportGif():
from drawBot.context.tools.gifTools import generateGif
destinationPath = set.pathExport + "/movie.gif"
images = []
durations = []
for frame in range(set.frames):
path = set.pathExport + set.exportFileName + str(frame) + "." + set.exportFileType
images.append(path)
durations.append(set.duration)
generateGif(images, destinationPath, durations)
if __name__ == '__main__':
exportGif()
To end with some shameless self promotion :)
You can find a few example on my instagram account @studio.ratata I'll be posting some more stuff soon what I did with DrawBot and Processing.
Have fun with the script!
Tim