背景信息:我的3D粒子数量很多(N)。对于具有某些属性的所有粒子对[i,j],我计算一个几何因子c [i,j]。然后,我想总结一个固定i的所有对[i,j]的贡献,并将其称为c [i](并对所有粒子i重复此过程)。
通常,相关对的数量比N ^ 2小得多,因此使用(numpy),具有(N,N)维数组C的位置[i,j]处具有相关信息,而其他位置有很多零,但在内存使用方面也非常低效。因此,现在我只是将相关对的C [i,j]和形成这些对的粒子存储在一维数组中。
在一个示例中可能最好地说明了这一点:说,我有两对粒子(3,5)和(3,10)组成。从示意图上看,我的变量如下所示(需要重复计算):
i = [3,3,5,10] #list of particles i that form a pair
j = [5,10,3,3] #corresponding particles j (not used in the later example)
cij = [c35,c310,-c35,-c310] #(with actual numbers in reality)
现在,实际上归结为找到一种有效的矢量化方法来重写以下for循环:
part_list=np.arange(N)
for a in part_list:
cond = np.where(i == a)
ci[a] = np.sum(cij[cond])
我曾想过但想避免的其他解决方案:
a)并行化for循环:不可行b / c这是嵌入在我想在某个时候并行化的外部循环中。
b)用C编写for循环,然后将其包装到Python中:对于这个(希望如此)相当简单的问题,这似乎有点过头了。
您可以通过获得所需的东西np.bincount
。如果您的粒子从0开始按顺序编号,则可以简单地执行以下操作:
ci = np.bincount(i, weights= cij)
要查看其作用,请执行以下操作:
>>> i = [3, 3, 5, 10]
>>> j = [5, 10, 3, 3]
>>> cij = [0.1, 0.2, -0.1, -0.2]
>>> np.bincount(i, weights= cij)
array([ 0. , 0. , 0. , 0.3, 0. , -0.1, 0. , 0. , 0. , 0. , -0.2])
如果您不希望所有这些额外的零,则可以执行以下操作:
>>> unq_i, inv_i = np.unique(i, return_inverse=True)
>>> unq_ci = np.bincount(inv_i, weights=cij)
>>> unq_i
array([ 3, 5, 10])
>>> unq_ci
array([ 0.3, -0.1, -0.2])
然后,您可以通过执行以下操作来分配这些唯一值:
ci[unq_i] = unq_ci
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句