【发布时间】:2019-08-15 21:16:28
【问题描述】:
我发现numpy.sin 在参数大小为 8192 时表现不同。不同之处在于性能和返回的值。有人能解释一下这种效果吗?
例如,让我们计算 sin(pi/4):
x = np.pi*0.25
for n in range(8191, 8195):
xx = np.repeat(x, n)
%timeit np.sin(xx)
print(n, np.sin(xx)[0])
64.7 µs ± 194 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
8191 0.7071067811865476
64.6 µs ± 166 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
8192 0.7071067811865476
20.1 µs ± 189 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
8193 0.7071067811865475
21.8 µs ± 13.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
8194 0.7071067811865475
超过 8192 个元素限制后,计算速度提高了 3 倍以上,并给出了不同的结果:最后一位数字变为 5 而不是 6。
当我尝试以其他方式计算相同的值时:
- C++
std::sin(Visual Studio 2017,Win32 平台)给出 0.7071067811865475; - C++
std::sin(Visual Studio 2017,x64 平台)给出 0.70710678118654756; -
math.sin给出 0.7071067811865476,这是合乎逻辑的,因为我使用的是 64 位 Python。
我在 NumPy 文档及其代码中都找不到任何解释。
更新 #2:很难相信,但将 sin 替换为 sqrt 给出了以下结果:
44.2 µs ± 751 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
8191 0.8862269254527579
44.1 µs ± 543 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
8192 0.8862269254527579
10.3 µs ± 105 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
8193 0.886226925452758
10.4 µs ± 4.41 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
8194 0.886226925452758
更新:np.show_config() 输出:
mkl_info:
libraries = ['mkl_rt']
library_dirs = ['C:/GNU/Anaconda3\\Library\\lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\include', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\lib', 'C:/GNU/Anaconda3\\Library\\include']
blas_mkl_info:
libraries = ['mkl_rt']
library_dirs = ['C:/GNU/Anaconda3\\Library\\lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\include', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\lib', 'C:/GNU/Anaconda3\\Library\\include']
blas_opt_info:
libraries = ['mkl_rt']
library_dirs = ['C:/GNU/Anaconda3\\Library\\lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\include', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\lib', 'C:/GNU/Anaconda3\\Library\\include']
lapack_mkl_info:
libraries = ['mkl_rt']
library_dirs = ['C:/GNU/Anaconda3\\Library\\lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\include', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\lib', 'C:/GNU/Anaconda3\\Library\\include']
lapack_opt_info:
libraries = ['mkl_rt']
library_dirs = ['C:/GNU/Anaconda3\\Library\\lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\include', 'C:\\Program Files (x86)\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\mkl\\lib', 'C:/GNU/Anaconda3\\Library\\include']
【问题讨论】:
-
不管怎样,在上述所有情况下,我在 x86_64 Linux 上使用 Python 3.7.3rc1 和 2.7.16rc1 看到
0.7071067811865475。 -
可以在 Windows 10 64 位中使用 CPython 3.6.7 和 NumPy 1.15.4 Anaconda (w/ MKL) 重现。
-
@aparpara:这很尴尬,但我实际上不知道如何运行 timeit 的东西。如果你给我一个提示,我会给你数字:-)
-
@gspr,%timeit 是 IPython 的魔法。不用的话可以用
python from timeit import timeit for n in range(8191, 8195): print(timeit("np.sin(np.repeat(x, n))", setup="from __main__ import np, x, n", number=10000)) print(n, np.sin(np.repeat(x, n))[0]) -
几乎可以肯定是 Anaconda 和 Intel MKL 的问题;参看。 github.com/numpy/numpy/issues/11448 和 github.com/ContinuumIO/anaconda-issues/issues/9129.
标签: python numpy anaconda intel-mkl