Drawbot Multiprocessing



  • 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

    # 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

    # 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