【问题标题】:Numpy sum gets faster with more entriesNumpy sum 随着更多条目变得更快
【发布时间】:2016-10-09 12:20:35
【问题描述】:

我已经测量了 numpy 的 sum 函数添加一定数量的值所需的时间。 下面的曲线表示 numpy 的 sum 函数(绿色)和标准 python for 循环(蓝色)将所有元素每个元素相加所需的时间。 因此,例如,在 101 个元素的数组上使用 numpy 的 sum 函数时,每个元素平均需要 2-19 秒来处理。

代码如下:

random_vector = np.random.random(10**7)

def for_sum(vector, n):
    sum = 0   

    start_time = time.perf_counter()
    for i in range(n):
        sum += vector[i]

    return time.perf_counter() - start_time

def numpy_sum(vector, n):
    new_vector = vector[:n]

    start_time = time.perf_counter()
    np.sum(new_vector)

    return time.perf_counter() - start_time

# determines the number of elements we should sum
spaced_values = np.logspace(1, 7, num=30, dtype=int)

# Measure time for for loops, per entry
for_sum_times_per_entry = np.zeros(0)
for i in spaced_values:
    for_sum_times_per_entry = np.append(for_sum_times_per_entry, for_sum(random_vector, i)/i)

# Measure time for numpy sum function, per entry
numpy_sum_times_per_entry = np.zeros(0)
for i in spaced_values:
   numpy_sum_times_per_entry = np.append(numpy_sum_times_per_entry, numpy_sum(random_vector, i)/i)

# Plot the amount of time required to sum each entries
plt.loglog(spaced_values, for_sum_times_per_entry, basex=10, basey=2)
plt.loglog(spaced_values, numpy_sum_times_per_entry, basex=10, basey=2)
plt.xlabel("Number of values summed")
plt.ylabel("Single entry computing time (s)")
plt.show()    

numpy sum 曲线显示,随着要求和的元素总数的增加,1 个元素所需的处理时间越来越少。

这是因为什么?我的观点是 numpy 的 sum 函数有一定的开销,会增加处理时间。这种开销需要一定的时间,因此随着我们添加元素,它变得越来越不重要。

【问题讨论】:

  • 正确,np.sum(x) 有开销。对于初学者,它首先检查x.sum 是否存在,然后再执行。
  • 是的,这似乎是 func 调用开销,所以我想您可以计时 np.sum(np.array([])) 并将其从各种数据大小的计时中减去,以便计算该开销。

标签: python performance numpy sum


【解决方案1】:

Numpy 在后台使用 BLAS,因此对于 numpy.sum,您可以应用低级逻辑:如果整个阵列适合 CPU 缓存,您将看到一个平面配置文件。我机器上的 L1 缓存为 64KB,果然numpy.sum 的计算时间保持不变,只要您没有超过 64KB / 64 Bit/float ~ 8000 个浮点条目:

这个图是用

生成的
import math
import numpy
import perfplot


def for_sum(a):
    sum = 0.0
    for i in range(len(a)):
        sum += a[i]
    return sum


perfplot.show(
    setup=numpy.random.rand,
    kernels=[for_sum, numpy.sum, sum, math.fsum],
    labels=["for-sum", "numpy.sum", "sum", "math.fsum"],
    n_range=[2 ** k for k in range(18)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

【讨论】:

    猜你喜欢
    • 2016-04-16
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 2016-04-09
    • 2016-10-14
    • 2016-01-21
    • 2019-11-28
    • 2020-12-28
    相关资源
    最近更新 更多