Skip to content

Commit b055e38

Browse files
authored
AnalogCore Bugfixes for multi-param and GPU cores (#17)
1 parent fade4af commit b055e38

File tree

2 files changed

+28
-25
lines changed

2 files changed

+28
-25
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
55
[project]
66
name = "CrossSim"
77
description = "Accuracy simulator for analog in-memory computing"
8-
version = "3.0"
8+
version = "3.0.1"
99
license = {text = "BSD 3-Clause License"}
1010
dependencies = [
1111
"numpy",

simulator/cores/analog_core.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,10 @@ def __init__(
210210
self.num_cores_row = self.Ncores // ((ncol - 1) // NrowsMax + 1)
211211
self.num_cores_col = self.Ncores // self.num_cores_row
212212
self.cores = [
213-
[self._make_core(params_[r * c]) for c in range(self.num_cores_col)]
213+
[
214+
self._make_core(params_[r * self.num_cores_col + c])
215+
for c in range(self.num_cores_col)
216+
]
214217
for r in range(self.num_cores_row)
215218
]
216219

@@ -224,9 +227,9 @@ def __init__(
224227
# 3) Otherwise partition based on row/col_partition_strategy (max or even)
225228

226229
if nrow % self.num_cores_row == 0:
227-
self.NrowsVec = (nrow // self.num_cores_row) * np.ones(
230+
self.NrowsVec = (nrow // self.num_cores_row) * xp.ones(
228231
self.num_cores_row,
229-
dtype=np.int32,
232+
dtype=xp.int32,
230233
)
231234
else:
232235
# prio_partition = True in (
@@ -321,15 +324,15 @@ def set_matrix(
321324
Raises:
322325
ValueError: Matrix is not valid for the input parameters.
323326
"""
324-
matrix = np.asarray(matrix)
327+
matrix = xp.asarray(matrix)
325328
if self.shape != matrix.shape:
326329
raise ValueError("Matrix shape must match AnalogCore shape")
327330

328331
if verbose:
329-
print("Min/Max matrix values", np.min(matrix), np.max(matrix))
332+
print("Min/Max matrix values", xp.min(matrix), xp.max(matrix))
330333

331334
if (
332-
matrix.dtype == np.complex64 or matrix.dtype == np.complex128
335+
matrix.dtype == xp.complex64 or matrix.dtype == xp.complex128
333336
) and not self.complex_valued:
334337
raise ValueError(
335338
(
@@ -343,9 +346,9 @@ def set_matrix(
343346
# Break up complex matrix into real and imaginary quadrants
344347
if self.complex_valued:
345348
Nx, Ny = matrix.shape
346-
matrix_real = np.real(matrix)
347-
matrix_imag = np.imag(matrix)
348-
mcopy = np.zeros((2 * Nx, 2 * Ny), dtype=matrix_real.dtype)
349+
matrix_real = xp.real(matrix)
350+
matrix_imag = xp.imag(matrix)
351+
mcopy = xp.zeros((2 * Nx, 2 * Ny), dtype=matrix_real.dtype)
349352
mcopy[0:Nx, 0:Ny] = matrix_real
350353
mcopy[Nx:, 0:Ny] = matrix_imag
351354
mcopy[0:Nx, Ny:] = -matrix_imag
@@ -357,8 +360,8 @@ def set_matrix(
357360
# If the values would exceed this range then you would have to reprogram all
358361
# matrix values based on the new range, so instead we will clip and warn
359362
if error_mask:
360-
mat_max = np.max(matrix)
361-
mat_min = np.min(matrix)
363+
mat_max = xp.max(matrix)
364+
mat_min = xp.min(matrix)
362365

363366
# Adding an epsilon here to avoid erroreous errors
364367
if mat_max > (self.max + self._eps) or mat_min < (self.min - self._eps):
@@ -468,7 +471,7 @@ def get_matrix(self) -> npt.NDArray:
468471
if self.Ncores == 1:
469472
matrix = self.cores[0][0]._read_matrix()
470473
else:
471-
matrix = np.zeros((self.nrow, self.ncol))
474+
matrix = xp.zeros((self.nrow, self.ncol))
472475
for row, row_start, row_end in self.row_partition_bounds:
473476
for col, col_start, col_end in self.col_partition_bounds:
474477
matrix[row_start:row_end, col_start:col_end] = self.cores[row][
@@ -866,7 +869,7 @@ def __getitem__(self, item):
866869
def __setitem__(self, key, value):
867870
rslice, cslice, full_mask, _ = self._create_mask(key)
868871
expanded_mat = self.get_matrix()
869-
expanded_mat[rslice, cslice] = np.asarray(value)
872+
expanded_mat[rslice, cslice] = xp.asarray(value)
870873
error_mask = None if full_mask else (rslice, cslice)
871874
self.set_matrix(expanded_mat, error_mask=error_mask)
872875

@@ -950,21 +953,21 @@ def _set_limits_percentile(constraints, input_, reset=False):
950953
"""
951954
if (constraints.min is None or constraints.max is None) or reset:
952955
if constraints.percentile >= 1.0:
953-
X_max = np.max(np.abs(input_))
956+
X_max = xp.max(xp.abs(input_))
954957
X_max *= constraints.percentile
955958
min_ = -X_max
956959
max_ = X_max
957960

958961
elif constraints.percentile < 1.0:
959-
X_posmax = np.percentile(input_, 100 * constraints.percentile)
960-
X_negmax = np.percentile(input_, 100 - 100 * constraints.percentile)
961-
X_max = np.max(np.abs(np.array([X_posmax, X_negmax])))
962+
X_posmax = xp.percentile(input_, 100 * constraints.percentile)
963+
X_negmax = xp.percentile(input_, 100 - 100 * constraints.percentile)
964+
X_max = xp.max(xp.abs(xp.array([X_posmax, X_negmax])))
962965
min_ = -X_max
963966
max_ = X_max
964967

965968
# Ensure min_ and max_ aren't the same for uniform inputs
966969
if min_ == max_:
967-
eps = np.finfo(float).eps
970+
eps = xp.finfo(float).eps
968971
min_ -= eps
969972
max_ += eps
970973
return (min_, max_)
@@ -1054,7 +1057,7 @@ def set_matrix(
10541057
verbose: bool = False,
10551058
error_mask: tuple[slice, slice] | None = None,
10561059
) -> None:
1057-
matrix = np.asarray(matrix)
1060+
matrix = xp.asarray(matrix)
10581061
self.parent.set_matrix(matrix.T, verbose=verbose, error_mask=error_mask)
10591062

10601063
def matvec(self, vec: npt.ArrayLike) -> npt.NDArray:
@@ -1157,7 +1160,7 @@ def get_matrix(self) -> npt.NDArray:
11571160
def set_matrix(self, matrix: npt.ArrayLike, verbose: bool = False, error_mask=None):
11581161
# TODO: Do we need to do anything with error_mask here?
11591162
expanded_mat = self.parent.get_matrix()
1160-
expanded_mat[self.rslice, self.cslice] = np.asarray(matrix)
1163+
expanded_mat[self.rslice, self.cslice] = xp.asarray(matrix)
11611164
self.parent.set_matrix(
11621165
expanded_mat,
11631166
verbose=verbose,
@@ -1172,7 +1175,7 @@ def matvec(self, other: npt.ArrayLike) -> npt.NDArray:
11721175
f"Dimension mismatch: {self.shape}, {other.shape}",
11731176
)
11741177

1175-
vec_in = np.zeros(self.parent.shape[1], dtype=other.dtype)
1178+
vec_in = xp.zeros(self.parent.shape[1], dtype=other.dtype)
11761179
vec_in[self.cslice] = other.flatten()
11771180

11781181
vec_out = self.parent.matvec(vec_in)
@@ -1195,7 +1198,7 @@ def matmat(self, other: npt.ArrayLike) -> npt.NDArray:
11951198
# out-of-slice rows
11961199
# For col slices we're just leaving empty entires in the input matrix
11971200
# corrosponding to missing rows
1198-
mat_in = np.zeros((self.parent.shape[1], other.shape[1]), dtype=other.dtype)
1201+
mat_in = xp.zeros((self.parent.shape[1], other.shape[1]), dtype=other.dtype)
11991202
for i in range(self.parent.shape[1])[self.cslice]:
12001203
mat_in[i] = other[(i - self.cslice.start) // self.cslice.step]
12011204
mat_out = self.parent.matmat(mat_in)
@@ -1209,7 +1212,7 @@ def vecmat(self, other: npt.ArrayLike) -> npt.NDArray:
12091212
f"Dimension mismatch: {other.shape}, {self.shape} ",
12101213
)
12111214

1212-
vec_in = np.zeros(self.parent.shape[0], dtype=other.dtype)
1215+
vec_in = xp.zeros(self.parent.shape[0], dtype=other.dtype)
12131216
vec_in[self.rslice] = other.flatten()
12141217

12151218
vec_out = self.parent.vecmat(vec_in)
@@ -1228,7 +1231,7 @@ def rmatmat(self, other: npt.ArrayLike) -> npt.NDArray:
12281231
f"Dimension mismatch: {other.shape}, {self.shape}",
12291232
)
12301233

1231-
mat_in = np.zeros((other.shape[0], self.parent.shape[0]), dtype=other.dtype)
1234+
mat_in = xp.zeros((other.shape[0], self.parent.shape[0]), dtype=other.dtype)
12321235
for i in range(self.parent.shape[0])[self.rslice]:
12331236
mat_in.T[i] = other.T[(i - self.rslice.start) // self.rslice.step]
12341237

0 commit comments

Comments
 (0)