From 7285950786ab84aa5dca7901419b07278605a4b0 Mon Sep 17 00:00:00 2001 From: Marvin Poul Date: Thu, 1 Sep 2022 16:36:00 +0200 Subject: [PATCH] Avoid excessive memory allocation when repeating SparseList Previous code allocated an array and a list for all atoms (not just entries) in the SparseList and then in a loop repeatedly called np.array on it, which creates copies. This gets very expensive when structures are large (>1k atoms) and is not necessary here. --- .../atomistics/structure/sparse_list.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pyiron_atomistics/atomistics/structure/sparse_list.py b/pyiron_atomistics/atomistics/structure/sparse_list.py index 5cf761119..902a5cd92 100644 --- a/pyiron_atomistics/atomistics/structure/sparse_list.py +++ b/pyiron_atomistics/atomistics/structure/sparse_list.py @@ -253,12 +253,13 @@ def __add__(self, other): def __mul__(self, other): if not isinstance(other, Integral): raise ValueError("Multiplication defined only for SparseArray*integers") - overall_list = other * np.arange(len(self)).tolist() - new_dic = dict() - for k in self.keys(): - for val in np.argwhere(np.array(overall_list) == k).flatten(): - new_dic[val] = self[k] - return self.__class__(new_dic, default=self._default, length=other * len(self)) + new_dict = {} + length = len(self) + for rep in range(other): + offset = rep * length + for k in self.keys(): + new_dict[k + offset] = self[k] + return self.__class__(new_dict, default=self._default, length=other * length) def __rmul__(self, other): if isinstance(other, Integral):