Skip to content

Commit 38bea94

Browse files
authored
Merge pull request #153 from JdeRobot/python-shared-memory
First implementation of wires using Python 3.8s shared memory
2 parents 2da76ae + f25ad68 commit 38bea94

25 files changed

+413
-775
lines changed

backend/staticfiles/synthesis/console.py

-148
This file was deleted.

backend/staticfiles/synthesis/lib/block.py

-48
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class InvalidOutputNameException(Exception):
2+
"""Raised when Output name has not been declared in ports"""
3+
4+
5+
class InvalidInputNameException(Exception):
6+
"""Raised when Input name has not been declared in ports"""
7+
8+
class InvalidParameterNameException(Exception):
9+
"""Raised when Parameter name has not been declared in ports"""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from multiprocessing import shared_memory
2+
3+
import numpy as np
4+
from lib.exceptions import InvalidInputNameException
5+
from lib.utils import create_ndbuffer
6+
7+
8+
def create_readonly_wire(name):
9+
try:
10+
shm = shared_memory.SharedMemory(name, create=False)
11+
except FileNotFoundError:
12+
shm = None
13+
return shm
14+
15+
16+
class Inputs:
17+
def __init__(self, input_data) -> None:
18+
self.inputs = input_data
19+
20+
def _read_npy_matrix(self, name, dtype):
21+
if self.inputs[name].get("created", False):
22+
dim = create_ndbuffer((1,), np.int64, self.inputs[name]["dim"].buf)[:][0]
23+
shape = create_ndbuffer((dim,), np.int64, self.inputs[name]["shape"].buf)
24+
data = create_ndbuffer(shape, dtype, self.inputs[name]["data"].buf)
25+
else:
26+
wire_name = self.inputs[name]["wire"]
27+
data_wire = create_readonly_wire(wire_name)
28+
shape_wire = create_readonly_wire(wire_name + "_shape")
29+
dim_wire = create_readonly_wire(wire_name + "_dim")
30+
if data_wire is None or shape_wire is None or dim_wire is None:
31+
return None
32+
33+
self.inputs[name]["dim"] = dim_wire
34+
dim = create_ndbuffer((1,), np.int64, dim_wire.buf)[:][0]
35+
self.inputs[name]["shape"] = shape_wire
36+
shape = create_ndbuffer((dim,), np.int64, shape_wire.buf)
37+
self.inputs[name]["data"] = data_wire
38+
data = create_ndbuffer(shape, dtype, data_wire.buf)
39+
self.inputs[name]["created"] = True
40+
41+
return data
42+
43+
def read_image(self, name):
44+
if self.inputs.get(name) is None:
45+
raise InvalidInputNameException(f"{name} is not declared in inputs")
46+
47+
data = self._read_npy_matrix(name, np.uint8)
48+
return data
49+
50+
def read_number(self, name):
51+
if self.inputs.get(name) is None:
52+
raise InvalidInputNameException(f"{name} is not declared in inputs")
53+
54+
number = None
55+
if self.inputs[name].get("created", False):
56+
number = self.inputs[name]["data"][:][0]
57+
else:
58+
wire_name = self.inputs[name]["wire"]
59+
data_wire = create_readonly_wire(wire_name)
60+
if data_wire is not None:
61+
self.inputs[name]["data"] = create_ndbuffer(
62+
(1,), np.float64, data_wire.buf
63+
)
64+
number = self.inputs[name]["data"][:][0]
65+
self.inputs[name]["created"] = True
66+
67+
return number
68+
69+
def read_array(self, name):
70+
if self.inputs.get(name) is None:
71+
raise InvalidInputNameException(f"{name} is not declared in inputs")
72+
73+
data = self._read_npy_matrix(name, np.float64)
74+
return data
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from multiprocessing import shared_memory
2+
3+
import numpy as np
4+
from lib.exceptions import InvalidOutputNameException
5+
from lib.utils import create_ndbuffer
6+
7+
8+
class Outputs:
9+
def __init__(self, output_data) -> None:
10+
self.outputs = output_data
11+
self.shms = []
12+
13+
def _create_wire(self, name, size):
14+
shm = shared_memory.SharedMemory(name=name, create=True, size=size)
15+
self.shms.append(shm)
16+
return shm
17+
18+
def _share_npy_matrix(self, name, matrix, shape):
19+
dim = np.array([len(matrix.shape)], dtype=np.int64)
20+
if self.outputs[name].get("created", False):
21+
self.outputs[name]["shape"][:] = shape[:]
22+
self.outputs[name]["data"][:] = matrix[:]
23+
else:
24+
wire_name = self.outputs[name]["wire"]
25+
data_wire = self._create_wire(wire_name, matrix.nbytes)
26+
shape_wire = self._create_wire(wire_name + "_shape", shape.nbytes)
27+
dim_wire = self._create_wire(wire_name + "_dim", dim.nbytes)
28+
self.outputs[name]["dim"] = create_ndbuffer((1,), np.int64, dim_wire.buf)
29+
self.outputs[name]["dim"][:] = dim[:]
30+
self.outputs[name]["shape"] = create_ndbuffer(
31+
shape.shape, shape.dtype, shape_wire.buf
32+
)
33+
self.outputs[name]["shape"][:] = shape[:]
34+
self.outputs[name]["data"] = create_ndbuffer(
35+
shape, matrix.dtype, data_wire.buf
36+
)
37+
self.outputs[name]["data"][:] = matrix[:]
38+
self.outputs[name]["created"] = True
39+
40+
def share_image(self, name, image):
41+
if self.outputs.get(name) is None:
42+
raise InvalidOutputNameException(f"{name} is not declared in outputs")
43+
44+
image = np.array(image, dtype=np.uint8)
45+
if len(image.shape) != 2 and len(image.shape) != 3:
46+
raise ValueError("Image must be 2D or 3D")
47+
48+
shape = (
49+
image.shape
50+
if len(image.shape) == 3
51+
else (image.shape[0], image.shape[1], 1)
52+
)
53+
shape = np.array(shape, dtype=np.int64)
54+
self._share_npy_matrix(name, image, shape)
55+
56+
def share_number(self, name, number):
57+
if self.outputs.get(name) is None:
58+
raise InvalidOutputNameException(f"{name} is not declared in outputs")
59+
60+
if self.outputs[name].get("created", False):
61+
self.outputs[name]["data"][:] = number
62+
else:
63+
wire_name = self.outputs[name]["wire"]
64+
data_wire = self._create_wire(
65+
wire_name, np.array([1], dtype=np.float64).nbytes
66+
)
67+
self.outputs[name]["data"] = create_ndbuffer(
68+
(1,), np.float64, data_wire.buf
69+
)
70+
self.outputs[name]["data"][:] = number
71+
self.outputs[name]["created"] = True
72+
73+
def share_array(self, name, array):
74+
if self.outputs.get(name) is None:
75+
raise InvalidOutputNameException(f"{name} is not declared in outputs")
76+
array = np.array(array, dtype=np.float64)
77+
self._share_npy_matrix(name, array, np.array(array.shape, dtype=np.int64))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from lib.exceptions import InvalidParameterNameException
2+
3+
4+
class Parameters:
5+
def __init__(self, parameter_data) -> None:
6+
self.parameters = parameter_data
7+
8+
def read_number(self, name):
9+
if self.parameters.get(name) is None:
10+
raise InvalidParameterNameException(f"{name} is not declared in parameters")
11+
12+
return float(self.parameters[name])
13+
14+
def read_string(self, name):
15+
if self.parameters.get(name) is None:
16+
raise InvalidParameterNameException(f"{name} is not declared in parameters")
17+
18+
return str(self.parameters[name])
19+
20+
def read_bool(self, name):
21+
if self.parameters.get(name) is None:
22+
raise InvalidParameterNameException(f"{name} is not declared in parameters")
23+
24+
return bool(self.parameters[name])

0 commit comments

Comments
 (0)