2

编辑添加:我认为 numba 基准测试不公平,请注意以下几点

我正在尝试对以下用例的数字处理数据的不同方法进行基准测试:

  1. 相当大的数据集(100,000+ 条记录)
  2. 100 多行相当简单的代码 (z = x + y)
  3. 不需要排序或索引

换句话说,不需要系列和数据帧的完全通用性,尽管它们包含在 b/c 中,但它们仍然是封装数据的便捷方式,并且通常需要进行预处理或后处理,这确实需要 pandas 的通用性numpy 数组。

问题:基于此用例,以下基准是否合适,如果不合适,我该如何改进它们?

# importing pandas, numpy, Series, DataFrame in standard way
from numba import jit
nobs = 10000
nlines = 100

def proc_df():
   df = DataFrame({ 'x': np.random.randn(nobs),
                    'y': np.random.randn(nobs) })
   for i in range(nlines):
      df['z'] = df.x + df.y
   return df.z

def proc_ser():
   x = Series(np.random.randn(nobs))
   y = Series(np.random.randn(nobs))
   for i in range(nlines):
      z = x + y
   return z

def proc_arr():
   x = np.random.randn(nobs)
   y = np.random.randn(nobs)
   for i in range(nlines):
      z = x + y
   return z

@jit
def proc_numba():
   xx = np.random.randn(nobs)
   yy = np.random.randn(nobs)
   zz = np.zeros(nobs)
   for j in range(nobs):
      x, y = xx[j], yy[j]
      for i in range(nlines):
         z = x + y
      zz[j] = z
   return zz

结果(Win 7、3 岁的 Xeon 工作站(四核)。标准和最近的 anaconda 发行版或非常接近。)

In [1251]: %timeit proc_df()
10 loops, best of 3: 46.6 ms per loop

In [1252]: %timeit proc_ser()
100 loops, best of 3: 15.8 ms per loop

In [1253]: %timeit proc_arr()
100 loops, best of 3: 2.02 ms per loop

In [1254]: %timeit proc_numba()
1000 loops, best of 3: 1.04 ms per loop   # may not be valid result (see note below)

编辑以添加(响应 jeff)将 df/series/array 传递给函数而不是在函数内部创建它们的替代结果(即将包含“randn”的代码行从内部函数移动到外部函数):

10 loops, best of 3: 45.1 ms per loop
100 loops, best of 3: 15.1 ms per loop
1000 loops, best of 3: 1.07 ms per loop
100000 loops, best of 3: 17.9 µs per loop   # may not be valid result (see note below)

注意 numba 结果:我认为 numba 编译器必须在 for 循环上进行优化,并将 for 循环减少到单次迭代。我不知道,但这是我能想到的唯一解释,因为它不能比 numpy 快 50 倍,对吧?这里的后续问题: 为什么 numba 比这里的 numpy 快?

4

2 回答 2

5

好吧,您在这里并没有真正计时相同的事情(或者更确切地说,您正在计时不同的方面)。

例如

In [6]:    x = Series(np.random.randn(nobs))

In [7]:    y = Series(np.random.randn(nobs))

In [8]:  %timeit x + y
10000 loops, best of 3: 131 µs per loop

In [9]:  %timeit Series(np.random.randn(nobs)) + Series(np.random.randn(nobs))
1000 loops, best of 3: 1.33 ms per loop

所以 [8] 乘以实际操作,而 [9] 包括系列创建(和随机数生成)的开销加上实际操作

另一个例子是proc_servs proc_df。这proc_df包括分配 DataFrame 中特定列的开销(对于初始创建和随后的重新分配实际上是不同的)。

所以创建结构(你也可以计时,但这是一个单独的问题)。执行完全相同的操作并为它们计时。

此外,您说您不需要对齐。Pandas 默认为您提供此功能(并且没有真正简单的方法可以将其关闭,尽管它只是一个简单的检查它们是否已经对齐)。在 numba 中,您需要“手动”对齐它们。

于 2014-09-18T15:21:31.003 回答
1

跟进@Jeff 的回答。代码可以进一步优化。

nobs = 10000
x = pd.Series(np.random.randn(nobs))
y = pd.Series(np.random.randn(nobs))

%timeit proc_ser()
%timeit x + y
%timeit x.values + y.values

100 loops, best of 3: 11.8 ms per loop
10000 loops, best of 3: 107 µs per loop
100000 loops, best of 3: 12.3 µs per loop
于 2016-08-21T18:54:38.103 回答