Я пытаюсь узнать что-то немного новое в каждом мини-проекте, который я делаю. Я создал программу Game of Life (https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life).
Это включает массив numpy, где каждая точка в массиве ("ячейка") имеет целочисленное значение. Чтобы развить состояние игры, вы должны вычислить для каждой ячейки сумму всех значений соседей (8 соседей).
Соответствующий класс в моем коде выглядит следующим образом, где evolve()
занимает одно xxx_method
методов. Он отлично работает для conv_method
и loop_method
, но я хочу использовать многопроцессорность (которая, как я определил, должна работать, в отличие от многопоточности?) На loop_method
, чтобы увидеть какое-либо увеличение производительности. Я чувствую, что это должно работать, так как каждый расчет независим. Я попробовал наивный подход, но на самом деле недостаточно хорошо понимаю многопроцессорный модуль. Могу ли я также использовать его в методе evolve()
, так как я снова чувствую, что каждый расчет в двойных циклах for
независим.
Любая помощь приветствуется, включая комментарии общего кода.
Редактировать - я получаю RuntimeError, которую я почти ожидаю, так как мое понимание многопроцессорности недостаточно хорошее. Что нужно сделать с кодом, чтобы он заработал?
class GoL:
""" Game Engine """
def __init__(self, size):
self.size = size
self.grid = Grid(size) # Grid is another class ive defined
def evolve(self, neigbour_sum_func):
new_grid = np.zeros_like(self.grid.cells) # start with everything dead, only need to test for keeping/turning alive
neighbour_sum_array = neigbour_sum_func()
for i in range(self.size):
for j in range(self.size):
cell_sum = neighbour_sum_array[i,j]
if self.grid.cells[i,j]: # already alive
if cell_sum == 2 or cell_sum == 3:
new_grid[i,j] = 1
else: # test for dead coming alive
if cell_sum == 3:
new_grid[i,j] = 1
self.grid.cells = new_grid
def conv_method(self):
""" Uses 2D convolution across the entire grid to work out the neighbour sum at each cell """
kernel = np.array([
[1,1,1],
[1,0,1],
[1,1,1]],
dtype=int)
neighbour_sum_grid = correlate2d(self.grid.cells, kernel, mode='same')
return neighbour_sum_grid
def loop_method(self, partition=None):
""" Also works out neighbour sum for each cell, using a more naive loop method """
if partition is None:
cells = self.grid.cells # no multithreading, just work on entire grid
else:
cells = partition # just work on a set section of the grid
neighbour_sum_grid = np.zeros_like(cells) # copy
for i, row in enumerate(cells):
for j, cell_val in enumerate(row):
neighbours = cells[i-1:i+2, j-1:j+2]
neighbour_sum = np.sum(neighbours) - cell_val
neighbour_sum_grid[i,j] = neighbour_sum
return neighbour_sum_grid
def multi_loop_method(self):
cores = cpu_count()
procs = []
slices = []
if cores == 2: # for my VM, need to impliment generalised method for more cores
half_grid_point = int(SQUARES / 2)
slices.append(self.grid.cells[0:half_grid_point])
slices.append(self.grid.cells[half_grid_point:])
else:
Exception
for sl in slices:
proc = Process(target=self.loop_method, args=(sl,))
proc.start()
procs.append(proc)
for proc in procs:
proc.join()