Skip to content

Instantly share code, notes, and snippets.

@jpivarski
Last active February 6, 2023 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpivarski/63ef88be8bd41d9ed24971b86824d189 to your computer and use it in GitHub Desktop.
Save jpivarski/63ef88be8bd41d9ed24971b86824d189 to your computer and use it in GitHub Desktop.
For https://youtu.be/lhqP50YVT-I (Game of Life in Python and Numba)
import time
import numpy as np
import numba as nb
# This could also be done without a class, using @nb.jit directly.
# It just seems natural to use a class. (That *might* slow it down a little; haven't tested it.)
spec = [
("width", nb.int32),
("height", nb.int32),
("board", nb.bool_[:, :]),
("next_board", nb.bool_[:, :]),
]
@nb.experimental.jitclass(spec)
class Automata:
def __init__(self, width, height):
self.width = width
self.height = height
self.board = np.zeros((width, height), np.bool_)
self.next_board = np.zeros((width, height), np.bool_) # double-buffer
def add_glider(self, x, y):
wrap_x = x if x < self.width else x
wrap_y = y if y < self.height else y
self.board[wrap_x + 0, wrap_y + 0] = True
self.board[wrap_x + 1, wrap_y + 1] = True
self.board[wrap_x + 2, wrap_y + 1] = True
self.board[wrap_x + 0, wrap_y + 2] = True
self.board[wrap_x + 1, wrap_y + 2] = True
def step(self):
for x in range(self.width):
for y in range(self.height):
num_neighbors = 0
for step_x in range(-1, 2):
for step_y in range(-1, 2):
if step_x != 0 or step_y != 0:
wrap_x = (x + step_x) % self.width
wrap_y = (y + step_y) % self.height
num_neighbors += self.board[wrap_x, wrap_y]
if self.board[x, y] and 1 < num_neighbors < 4:
self.next_board[x, y] = True
elif not self.board[x, y] and num_neighbors == 3:
self.next_board[x, y] = True
else:
self.next_board[x, y] = False
# copy next_board into board
self.board[:] = self.next_board
def steps(self, num_steps):
# get the loop over num_steps *inside* the compiled part
for _ in range(num_steps):
self.step()
def show(self):
for y in range(self.height):
row = ["."] * self.width
for x in range(self.width):
if self.board[x, y]:
row[x] = "X"
print("".join(row))
obj = Automata(40, 20)
obj.add_glider(18, 0)
# ensure that it's compiled before profiling (compilation takes 2.2 seconds)
obj.steps(0)
start_time = time.monotonic()
obj.steps(10000)
print(f"{time.monotonic() - start_time} seconds")
obj.show()

Result without @nb.experimental.jitclass(spec):

23.88778449900019 seconds
......................................X.
X......................................X
......................................XX
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................

Result with @nb.experimental.jitclass(spec):

0.2082922879999387 seconds
......................................X.
X......................................X
......................................XX
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
........................................
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment