给定一个二维数组A
,我必须继续在每列的第一行的值上加上+1,直到两列的总和等于相同的值为止,例如28。 >
这可能不是最好的解决方案,但是考虑到我想提出的观点,它会做到的。这只是一个简化的示例。在原始版本中,它基于概率分布是第一行还是第二行获得+1,并且各列之间有所不同。另外,由于列的第一行或第二行在上一个周期中获得+1所导致的概率分布变化,因此必须逐个进行。因此,列的求和和迭代是必要的。
import numpy as np
A = np.arange(20).reshape(2, 10)
print(A)
MASK = A.sum(axis=0) < 28
print(A.sum(axis=0) < 28)
while np.any(MASK):
LUCKYROW = np.repeat(0, np.count_nonzero(MASK))
A[LUCKYROW, MASK] += 1
MASK = A.sum(axis=0) < 28
print(A.sum(axis=0) < 28)
print(A)
让我们看一下输出:
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]]
[ True True True True True True True True True False]
[ True True True True True True True True True False]
[ True True True True True True True True False False]
[ True True True True True True True True False False]
[ True True True True True True True False False False]
[ True True True True True True True False False False]
[ True True True True True True False False False False]
[ True True True True True True False False False False]
[ True True True True True False False False False False]
[ True True True True True False False False False False]
[ True True True True False False False False False False]
[ True True True True False False False False False False]
[ True True True False False False False False False False]
[ True True True False False False False False False False]
[ True True False False False False False False False False]
[ True True False False False False False False False False]
[ True False False False False False False False False False]
[ True False False False False False False False False False]
[False False False False False False False False False False]
[[18 17 16 15 14 13 12 11 10 9]
[10 11 12 13 14 15 16 17 18 19]]
可以,但是为什么我要计算每个循环中每一列的总和?根据以前的周期,我知道哪一列的总和已经达到目标值。如果我利用这些信息,也许可以节省时间。
import numpy as np
A = np.arange(20).reshape(2, 10)
print(A)
MASK = A.sum(axis=0) < 28
print(A.sum(axis=0) < 28)
while np.any(MASK):
LUCKYROW = np.repeat(0, np.count_nonzero(MASK))
A[LUCKYROW, MASK] += 1
MASK[MASK] = A[:, MASK].sum(axis=0) < 28
print(A[:, MASK].sum(axis=0) < 28)
print(A)
输出:
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]]
[ True True True True True True True True True False]
[ True True True True True True True True True]
[ True True True True True True True True]
[ True True True True True True True True]
[ True True True True True True True]
[ True True True True True True True]
[ True True True True True True]
[ True True True True True True]
[ True True True True True]
[ True True True True True]
[ True True True True]
[ True True True True]
[ True True True]
[ True True True]
[ True True]
[ True True]
[ True]
[ True]
[]
[[18 17 16 15 14 13 12 11 10 9]
[10 11 12 13 14 15 16 17 18 19]]
似乎可行。尽管出现了一个问题。它不比第一个解决方案快。我尝试使用25000列和74998作为目标值,但是它们在时间上大致相等。
我认为我可能对ndarray操作或ndarray索引有一个基本的误解。第二种解决方案在每个周期中所做的计算将越来越少,因此我希望性能得到显着改善。我找不到解释。我的思路在哪里出错?
答案 0 :(得分:1)
由于您仅更改第一行,因此无需在每次迭代时重新计算列的总和。实际上,由于唯一的变化是在第一行的某些元素上加了1,所以根本不需要迭代。
public List<SelectOption> getContactFields(){
这可能无法通过更复杂的计算来实现,但是总之,这是一个简单的捷径。
您的“更快”的代码实际上没有更快地运行可能有一些原因。
首先,是对代码进行实际性能分析的荣誉。
第一个原因是A = np.arange(20).reshape(2, 10)
s = A.sum(0)
d = max(s) - s
A[0] += d
>>> A
array([[18, 17, 16, 15, 14, 13, 12, 11, 10, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
很小。
通常,A
仅对数组中成千上万个元素的速度有好处。
第二,在“更快”的代码行
numpy
创建MASK[MASK] = A[:, MASK].sum(axis=0) < 28
索引的A
中所有行的副本。
这可能是一个相当昂贵的操作,因此使用MASK
对原始版本中的多余行进行求和可能会更快,因为它不需要多余的副本。
答案 1 :(得分:0)
关于索引如何影响总和的快速演示:
In [140]: x = np.arange(10000)
In [141]: timeit x.sum()
13.4 µs ± 183 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
即使使用快速切片view
,将一半的项目累加也不会节省那么多时间:
In [142]: timeit x[:5000].sum()
10.8 µs ± 78.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
高级索引编制或屏蔽操作较慢:
In [143]: %%timeit idx=np.arange(5000)
...: x[idx].sum()
21.3 µs ± 1.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [144]: %%timeit
...: x[x<=5000].sum()
34.4 µs ± 1.34 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
在现代计算机上,像加法这样的基本数学运算并不那么昂贵。在时间上,选择项和遍历数组与添加本身一样昂贵。