【问题标题】:How does dtype affect row and column operation speed in Numpy?dtype 如何影响 Numpy 中的行和列操作速度?
【发布时间】:2018-01-24 02:41:33
【问题描述】:

我试图了解如何最好地利用 numpy 数组的 C 排序来编写高性能代码。我的期望是遍历行的操作应该比遍历列的操作更快。事实上,我尝试的第一个例子就是这样:

X = np.ones((10000,10000),dtype='int64')
print(X.dtype)
print(X.flags)

%timeit np.sum(X,axis=0)

%timeit np.sum(X,axis=1)

这会产生输出:

int64
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
10 loops, best of 3: 79.6 ms per loop
10 loops, best of 3: 61.1 ms per loop

这是我的预期,因为沿行求和应该比沿列求和更快。

这是我非常困惑的地方。如果我将 dtype 更改为 float64,那么列操作的速度几乎是行操作的两倍:

X = np.ones((10000,10000),dtype='float')
print(X.dtype)
print(X.flags)

%timeit np.sum(X,axis=0)

%timeit np.sum(X,axis=1)

产生输出:

float64
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
10 loops, best of 3: 67.7 ms per loop
10 loops, best of 3: 123 ms per loop

有人能解释一下为什么会这样吗?

编辑:在 cmets 中建议我使用较小的矩阵 (1000,1000) 再试一次。当我跑步时:

import time
import numpy as np

X = np.ones((1000,1000),dtype='float')
print(X.dtype)
print(X.flags)

%timeit np.sum(X,axis=0)
%timeit np.sum(X,axis=1)

X = np.ones((1000,1000),dtype='int64')
print(X.dtype)
print(X.flags)

%timeit np.sum(X,axis=0)
%timeit np.sum(X,axis=1)

我得到输出:

float64
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
1000 loops, best of 3: 598 µs per loop
1000 loops, best of 3: 1.06 ms per loop
int64
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
1000 loops, best of 3: 788 µs per loop
1000 loops, best of 3: 632 µs per loop

所以效果持续存在。

【问题讨论】:

  • 您的numpypython 是什么版本?
  • @DanielF Python 3.6,Numpy 1.11.3。
  • 尝试减小X(即(1000,1000))的大小,看看时差是否在某个点从~200% 跳到~110%。您可能正在缓存。
  • 转载于 Win7/32B,python 3.5.2numpy 1.11.1
  • 实际上,我认为您必须使数组更大,至少在您正在操作的维度上,才能始终如一地看到差异。

标签: python numpy row-major-order


【解决方案1】:

我无法确认您在 OSX(各种 Python 版本)上的第二个结果 - 它与您的第一个结果相似:

In [27]: X = np.ones((10000,10000),dtype='float64')
    ...: print(X.dtype)
    ...: print(X.flags)
    ...: 
    ...: %timeit np.sum(X,axis=0)
    ...: 
    ...: %timeit np.sum(X,axis=1)
    ...: 
float64
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
10 loops, best of 3: 67.6 ms per loop
10 loops, best of 3: 62 ms per loop

编辑:我直接使用 timeit.repeat() 重复了您的所有计算:

import timeit
t = timeit.repeat('np.sum(X,axis=0)', setup="import numpy as np; X = np.ones((10000,10000),dtype='float64')", repeat=50, number=1); print(min(t));
t = timeit.repeat('np.sum(X,axis=1)', setup="import numpy as np; X = np.ones((10000,10000),dtype='float64')", repeat=50, number=1); print(min(t));
t = timeit.repeat('np.sum(X,axis=0)', setup="import numpy as np; X = np.ones((10000,10000),dtype='int64')", repeat=50, number=1); print(min(t));
t = timeit.repeat('np.sum(X,axis=1)', setup="import numpy as np; X = np.ones((10000,10000),dtype='int64')", repeat=50, number=1); print(min(t));

这些时间安排:

Python 2.7.13 |Continuum Analytics, Inc.| (default, Dec 20 2016, 23:05:08) 
IPython 5.3.0 -- An enhanced Interactive Python.
numpy 1.12.1

0.0637669563293 # float64, axis=0
0.0558688640594 # float64, axis=1
0.0669782161713 # int64, axis=0
0.0576930046082 # int64, axis=1

Python 3.6.2 |Continuum Analytics, Inc.| (default, Jul 20 2017, 13:14:59) 
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.
numpy 1.13.1

0.06289491400821134
0.05558946297969669
0.0670205659698695
0.057950171001721174

Python 3.5.3 |Continuum Analytics, Inc.| (default, Mar  6 2017, 12:15:08) 
IPython 5.3.0 -- An enhanced Interactive Python.
numpy 1.11.3

0.06345970398979262
0.05561513203429058
0.07043616304872558
0.057934076990932226

最后,在我的 Android 手机上:

Python 3.6.2 (default, Jul 19 2017, 11:01:41)
IPython 6.1.0
numpy 1.12.0

0.39130385394673795
0.24979593697935343
0.42852322908584028
0.28863119706511497

和Windows系统(python 3.4 32bit):

0.158213707338
0.149441164907
0.365552662475
0.128456460354

【讨论】:

  • 嗯...好的,我将不得不在另一台计算机上运行此代码。这很奇怪,因为我可以在我的机器上重现这个结果。
  • 我在我的机器@jmracek 上复制了它。也许是版本或硬件差异。您正在运行 AGN 的 numpypython 的哪个版本?
  • 我在 Microsoft Surface Pro 3 上运行 python 3.6 和 numpy 1.11.3。
  • 当我尝试这种替代计时方法时,我仍然得到与以前相同的结果。
  • @DanielF 所有测试都在 OSX 上。我编辑了答案以包含版本信息。
猜你喜欢
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多