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?

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

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…