Multiprocessing

Hello everyone. I want to write image.pixels using multiprocessing like here in the example bellow:

import bpy
import numpy as np
from random import random

from time import time

##################################
class dd:
    def __init__(self):
        self.tt = time()
    def t(self):
        print(time() - self.tt)
##################################

def calculate_rect_tile_pixels(current_tile, sx, sy, tiles):
    quotient, remainder = divmod(sy, tiles)
    
    ty = quotient
    py = ty * current_tile
    
    start = py * sx * 4
    end = (py + ty) * sx * 4
    if remainder:
        end += sx*4
    
    dim = end - start
    
    return start, end, dim

def get_draw(dim):
    draw = np.empty((int(dim / 4), 4), 'f')
    color = [random(), random(), random(), 1.0]
    for n in range(len(draw)):
        draw[n] = color
    draw = np.reshape(draw, dim)
    return draw

image = bpy.data.images["Untitled"]

sx, sy = image.size
pixels = image.pixels
len_pixels = len(pixels)

num_tiles = 6

tiles = [calculate_rect_tile_pixels(i, sx, sy, num_tiles) for i in range(num_tiles)]

draws = [get_draw(n[2]) for n in tiles]

d = dd()
for i in range(num_tiles):
    start, end, dim = tiles[i]
    draw = draws[i]
    
    image.pixels[start: end] = draw

d.t()


But I want to draw each tile using multiprocessing, dont using for i in range(num_tiles):
Actually, how can I do that?

Use cython, or c, or some other multithreaded compiled language. Python can do threading, but it’s all on a single process.

Hello :slight_smile:

Of course Python can do multiprocessing without cython :slight_smile:
Indeed the threading module is single process, but the multiprocessing module is perfect for this :slight_smile:


If you never used multiprocessing in Python, first I would advice you to try some simple examples on the net. HERE is the doc of multiprocessing


Basically, any job (even your’s) can be cut into smaller ones. You fill a list, let’s say A with jobs. You have a function which computes it, let’s say F. you fill a list let’s say B with the results.
So your “big” job would look like this :
(very simple code just to explain, single process)

#
# Here you create A, which is filled with sub jobs
#
B=[]  # The results
for a in A:
    b = F(a) # Computing a subjob
    B.append(b) # Saving result in B
#
# Here you take back results in B and compute the final result from small parts
#

If you are able to get the structure above, then it’s super easy to use multiprocessing :
Indeed, different workers (processes) can be assigned some elements of A to compute, and save it in B, in parallel


  • Considering this simple example
    The Multiprocessing is about binding the F function on a process. ( F would be the target argument of the Process Class )
  • For example if you have 8 CPUs you would create 8 processes.
    Then the “lists” (A and B) would be in fact not just a list, but a more high level class called Queue. It’s a class which is done for saving some list of data, and passing them to processes, or taking back results (uselly, both)
  • In order to make it “clean”, another usefull class is called Pool and will allow you to automatically distribute jobs from a list to processes, as soon as they finish the previous one they would start another, etc…

Hope this will help understanding the thing :slight_smile:

See you :slight_smile: ++
Tricotou