这项调查是由于scipy CI在最近几天(即1.14发布后)开始在传送带上
在我的家用计算机上(macOS,conda python 3.6.2,conda numpy):
>>> import numpy as np
>>> np.version.version
'1.14.0'
>>> np.min([1.0, 2.0, np.nan])
nan
>>> np.min([1.0, np.nan, 2.0])
nan
>>> np.min([np.nan, 1.0, 2.0])
nan
>>> np.min([np.nan, 1.0])
/Users/andrew/miniconda3/envs/dev3/lib/python3.6/site-packages/numpy/core/_methods.py:29: RuntimeWarning: invalid value encountered in reduce
return umr_minimum(a, axis, None, out, keepdims)
nan
在我的工作计算机上(macOS,conda python 3.6.2,在干净的环境中通过pip安装的numpy):
>>> import numpy as np
>>> np.version.version
'1.14.0'
>>> np.min([1., 2., 3., 4., np.nan])
nan
>>> np.min([1., 2., 3., np.nan, 4.])
nan
>>> np.min([1., 2., np.nan, 3., 4.])
nan
>>> np.min([1., np.nan, 2., 3., 4.])
nan
>>> np.min([np.nan, 1., 2., 3., 4.])
nan
>>> np.min([np.nan, 1.])
nan
>>> np.min([np.nan, 1., np.nan])
nan
>>> np.min([1., np.nan])
nan
>>> np.seterr(all='raise')
{'divide': 'warn', 'over': 'warn', 'under': 'ignore', 'invalid': 'warn'}
>>> np.min([1., np.nan])
nan
>>> np.min([np.nan, 1.])
nan
>>> np.min([np.nan, 1., 2., 3., 4.])
nan
>>> np.min([np.nan, 1., 2., 3., 4.])
nan
对于第一组代码示例,为什么前三个示例不产生警告,而仅导致最后一个警告?
在第二组示例中,根本没有发出警告。
外部参照scipy / scipy#8282,scipy / scipy#8279
我认为这里的另一点是,可能是不同的代码路径触发了不同的行为(我认为不是真正的numpy),例如,由于使用了AVX等,我想我有时看到矢量东西无法设置错误cpu标志,并且因为如果不使用它们,可能会显得有些随机。
Dunno如果这与它有很大关系,但是我希望它,numpy通常不会对浮点错误做太多事情。 除了检查是否发生任何事情。
而且正如Chuck所说,不幸的是,在不同的系统上,许多浮点错误标志是不同的。
好的,了解为什么错误仅在某些安装中发生而在其他安装中不发生。
scipy在可能包含NaN的数组上使用np.min的原因是,这是检查它们是否存在的快速方法。 numpy文档建议这样做是允许的:
将传播NaN值,即,如果至少一项是NaN,则相应的最小值也将是NaN。
鉴于这是np.min允许的使用案例之一,从使用角度来看,我完全不希望发出任何警告/错误。
(显然,还有其他方法可以实现这一点,例如np.isnan(arr).any()
,但这不会改变我上面的推理)
我猜这根本不是一个合理的变化。
+1完全没有警告
你好
我偶然发现了类似的不一致之处:
>>> import numpy
>>> import warnings
>>> warnings.simplefilter("always", category=RuntimeWarning)
>>> numpy.min(numpy.full((7,), numpy.nan, dtype=numpy.float64))
nan
>>> numpy.min(numpy.full((8,), numpy.nan, dtype=numpy.float64))
/home/user/env/lib/python3.6/site-packages/numpy/core/_methods.py:29: RuntimeWarning: invalid value encountered in reduce
return umr_minimum(a, axis, None, out, keepdims)
nan
为什么形状大于8会引发RuntimeWarning?
@NotSqrt @seberg当输入数组的大小变为8时,min根本无法正确传播NaN时,我看到了类似的行为:
> cat np-min-wat.py
import numpy as np
print "numpy version:", np.__version__
print ""
def show_min(input):
print ""
arr = np.array(input)
print arr.dtype, arr
print "this should be nan as per docs:", arr.min()
arr = np.array
input = [31., 487., np.nan, 10000., 10000., 19., 101., 22., 1000., 300., 10.]
for x in xrange(3, len(input) + 1):
show_min(input[0:x])
在OSX和Windows上显示这种相当奇怪的行为,但在Linux上则没有。使用python 2.7.13和numpy 1.14.2的fresh virtualenv:
numpy version: 1.14.2
/Users/kip/ac/Environments/test/lib/python2.7/site-packages/numpy/core/_methods.py:29: RuntimeWarning: invalid value encountered in reduce
return umr_minimum(a, axis, None, out, keepdims)
float64 [ 31. 487. nan]
this should be nan as per docs: nan
float64 [ 31. 487. nan 10000.]
this should be nan as per docs: nan
float64 [ 31. 487. nan 10000. 10000.]
this should be nan as per docs: nan
float64 [ 31. 487. nan 10000. 10000. 19.]
this should be nan as per docs: nan
float64 [ 31. 487. nan 10000. 10000. 19. 101.]
this should be nan as per docs: nan
float64 [ 31. 487. nan 10000. 10000. 19. 101. 22.]
this should be nan as per docs: 19.0
float64 [ 31. 487. nan 10000. 10000. 19. 101. 22. 1000.]
this should be nan as per docs: 19.0
float64 [ 31. 487. nan 10000. 10000. 19. 101. 22. 1000. 300.]
this should be nan as per docs: nan
float64 [ 31. 487. nan 10000. 10000. 19. 101. 22. 1000. 300.
10.]
this should be nan as per docs: nan
看到两个“这应该是docs的nan: 19.0 ”行吗?
同样,在numpy 1.13.1上没有出现警告(这是我第一次观察到此行为的地方。)
@kippr您从哪里获得NumPy的?
我猜这八个元素的边界可能与AVX512有关,问题是编译器和CPU的某种组合。 您在哪个cpus / compiler上看到问题?
@juliantaylor有想法吗?
对齐也可能会产生影响。
嗨@charris
感谢您看我的帖子..回答您的问题:
中央处理器
❃sysctl -n machdep.cpu.brand_string Intel(R)Core(TM)i7-6700K CPU @ 4.00GHz
NumPy是通过pip在我的Mac上以全新的virtualenv安装的(通过自制软件安装的python 2.7.13),所以我猜它使用了所有默认的编译器标记等?
我刚刚重新创建了虚拟环境并重新运行了pip安装,这看起来与我有关,但是安装时会出现很多消息。(附加完整日志。)请让我知道是否还有其他信息可以从构建目录或其他目录中退出,或者可以尝试使用编译标志。
[..]
Downloading numpy-1.14.2.zip (4.9MB):
Downloading from URL https://pypi.python.org/packages/0b/66/86185402ee2d55865c675c06a5cfef742e39f4635a4ce1b1aefd20711c13/numpy-1.14.2.zip#md5=080f01a19707cf467393e426382c7619 (from https://pypi.python.org/simple/numpy/)
...Downloading numpy-1.14.2.zip (4.9MB): 4.9MB downloaded
[..]
building library "npymath" sources
get_default_fcompiler: matching types: '['gnu95', 'nag', 'absoft', 'ibm', 'intel', 'gnu', 'g95', 'pg']'
customize Gnu95FCompiler
Found executable /usr/local/bin/gfortran
customize Gnu95FCompiler
customize Gnu95FCompiler using config
C compiler: clang -fno-strict-aliasing -fno-common -dynamic -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
compile options: '-Inumpy/core/src/private -Inumpy/core/src -Inumpy/core -Inumpy/core/src/npymath -Inumpy/core/src/multiarray -Inumpy/core/src/umath -Inumpy/core/src/npysort -I/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c'
clang: _configtest.c
clang _configtest.o -o _configtest
success!
removing: _configtest.c _configtest.o _configtest
谢谢
克里斯
ps可能不足为奇,但是max出现相同的行为:
numpy version: 1.14.2
arr.dtype, arr: float64 [ 31. 487. nan]
/Users/kip/ac/Environments/meh/lib/python2.7/site-packages/numpy/core/_methods.py:29: RuntimeWarning: invalid value encountered in reduce
return umr_minimum(a, axis, None, out, keepdims)
arr.min(): nan
/Users/kip/ac/Environments/meh/lib/python2.7/site-packages/numpy/core/_methods.py:26: RuntimeWarning: invalid value encountered in reduce
return umr_maximum(a, axis, None, out, keepdims)
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 31.0
arr.dtype, arr: float64 [ 31. 487. nan 10000.]
arr.min(): nan
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 31.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000.]
arr.min(): nan
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 31.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000. 19.]
arr.min(): nan
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 19.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000. 19. 101.]
arr.min(): nan
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 19.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000. 19. 101. 22.]
arr.min(): 19.0
arr.max(): 10000.0
np.amin(arr): 19.0
np.nanmin(arr): 19.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000. 19. 101. 22. 1000.]
arr.min(): 19.0
arr.max(): 10000.0
np.amin(arr): 19.0
np.nanmin(arr): 19.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000. 19. 101. 22. 1000. 300.]
arr.min(): nan
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 19.0
arr.dtype, arr: float64 [ 31. 487. nan 10000. 10000. 19. 101. 22. 1000. 300.
10.]
arr.min(): nan
arr.max(): nan
np.amin(arr): nan
np.nanmin(arr): 10.0
我使用的CPU具有相同的numpy版本(在arch上),该版本也具有AVX2和sse4.2功能,但在Linux上看不到它。 也许与mac / clang有关?
编辑/修订:(我尝试过挑衅一些对齐方式,没有检查警告部分,但是我看不到错误的结果部分)
我猜有一个cpu标志设置不正确,可能与编译器有关。
如果只是为了跟踪它,我们应该进行测试以证明这个问题。 @kippr是什么
np.min(np.diagflat([np.nan]*10), axis=0)
在您的安装上做什么?
嗨@charris
看起来还可以:
In [1]: import numpy as np
In [2]: np.min(np.diagflat([np.nan]*10), axis=0)
Out[2]: array([ nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])
但是我尝试了一些连击,发现了以下内容(请参阅最后一个,8个值和axis = 1):
In [3]: np.min(np.diagflat([np.nan]*10), axis=1)
Out[3]: array([ nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])
In [4]: np.min(np.diagflat([np.nan]*8), axis=0)
Out[4]: array([ nan, nan, nan, nan, nan, nan, nan, nan])
In [5]: np.min(np.diagflat([np.nan]*8), axis=1)
Out[5]: array([ nan, nan, 0., 0., nan, 0., nan, nan])
相当神秘..不确定是否完全有助于了解原因。
@seberg-是的,是的,我在Mac和Windows上都观察到了这种现象,但是linux很好。
谢谢
克里斯
@kippr这是一个非常令人不安的错误,因为它会影响基本操作,而该问题似乎并非源自NumPy。 我们可以尝试在MAC和Windows上关闭矢量化功能,看看是否有帮助。 您仅在Python 2.7上看到此问题吗?
我在NumPy中看不到任何会更改此行为1.14的内容。 也许OpenBLAS摆弄了控件...
@juliantaylor @VictorRodriguez有什么想法吗?
嗨@charris
我在Mac上的python 3中也看到了此行为:
Python 3.6.0 (default, Jan 23 2017, 20:09:28)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.min(np.diagflat([np.nan]*8), axis=1)
array([nan, nan, 0., 0., nan, 0., nan, nan])
>>> np.__version__
'1.14.2'
Nb我首先在Mac上的python 2.7下的NumPy版本1.13中注意到了此行为,因此它不是1.14中引入的回归:
Python 2.7.10 (default, Feb 7 2017, 00:08:15)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.min(np.diagflat([np.nan]*8), axis=1)
array([ nan, nan, 0., 0., nan, 0., nan, nan])
>>> np.__version__
'1.13.1'
并在cygwin / Windows中复制它:
$ python
Python 2.7.13 (default, Mar 13 2017, 20:56:15)
[GCC 5.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.min(np.diagflat([np.nan]*8), axis=1)
array([ nan, nan, 0., 0., nan, 0., nan, nan])
>>> np.__version__
'1.13.1'
但是在Linux中看不到这个问题:
Python 2.7.6 (default, Oct 26 2016, 20:32:47)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.min(np.diagflat([np.nan]*8), axis=1)
array([ nan, nan, nan, nan, nan, nan, nan, nan])
>>> np.__version__
'1.13.1'
@charris我在进行numpy性能优化的过程中看到过,openblas和编译器标志会影响numpy / scipy的行为(根据我的经验)。 我们可以采取的第一步是将其附加到C(使用openblas库)测试中,以便我们可以隔离行为并查看它是否可以复制。 还要仔细检查,这只是在MAC和Windows上对吗? 我在Linux上看不到这种现象(在avx补丁进入1.15版本之前,所以它们不会影响这个行为)。 @kippr您是如何在Mac / Windows中构建numpy的? 问候
嗨@VictorRodriguez
这是通过在两个平台上的pip安装来完成的,在Mac机壳中是一个全新的virtualenv。 参见上文,我在其中为pip粘贴了日志,其中包括python 2.7安装的编译输出。 (Python 3 pip安装似乎很麻烦。)
干杯克里斯
嗨伙计
我可以提供更多帮助的信息吗?
谢谢
在Mac(可能还有其他平台)上,由于编译器(在Mac上默认为clang / llvm而不是gcc)正在以一种有问题的方式重新排序SSE2命令,因此发生了该错误。 中的错误:
np.min(np.diagflat([np.nan]*8), axis=1)
之所以发生,是因为正在运行的代码是从以下位置生成的sse2_minimum_DOUBLE:
https://github.com/numpy/numpy/blob/d7d5cb3feccc1fc6cf57159e8b9fe0a733968706/numpy/core/src/umath/simd.inc.src#L1020
具体来说,让我们看一下第1041行中函数内的这段代码(我已经自动扩展了SSE2表单):
}
c1 = _mm_min_pd(c1, c2);
if (npy_get_floatstatus() & NPY_FPE_INVALID) {
*op = NPY_NAN;
}
else {
npy_double tmp = sse2_horizontal_min___m128d(c1);
....
}
编译器不了解c1分配和npy_get_floatstatus()是相关的,因此将代码更改为:
}
if (npy_get_floatstatus() & NPY_FPE_INVALID) {
*op = NPY_NAN;
}
else {
c1 = _mm_min_pd(c1, c2);
npy_double tmp = sse2_horizontal_min___m128d(c1);
....
}
这当然是胡说八道...我不知道什么是建议的方法,以使其在优化下不这样做。 (我认为其他平台对此有STDC FENV_ACCESS编译指示吗?)
也许由于此代码的更改已使用5年了,所以该错误是由新版本的clang和其他优化引起的吗?
谢谢@tzickel
自从许多个月前的高中毕业以来,我还没有写过C,所以我绝对不会想出解决这个问题的聪明方法,但是我确实尝试了一些方法来迫使编译器按照原始顺序进行评估:将上述if语句更改为:
if ((sizeof(c1) != 0) || (sizeof(c1) == 0) & npy_get_floatstatus() & NPY_FPE_INVALID) {
确实,一旦执行此操作,该错误就会消失。
(我还尝试了其他一些较简单的形式,以使编译器在if语句之前评估_mm_min_pd,例如,通过在if语句的两边以及在if / else块之后放置对c1的引用,全部无济于事。我怀疑它要么重新排序了,但总是运行c = _mm_min_pd分配,或者认为我的电话实际上是某种形式的noop。
但是无论如何,我都可以确认您已经确定了我所看到的错误,希望有人可以有一个很好的方法来提示编译器,使_mm_min_pd和npy_get_floatstatus的顺序保持不变。
好的,谷歌建议的另一件事也可以起作用:将c1标记为volatile:
变成:
/* load the first elements */
@vtype@ volatile c1 = @vpre@_load_@vsuf@((@type@*)&ip[i]);
@vtype@ c2 = @vpre@_load_@vsuf@((@type@*)&ip[i + stride]);
i += 2 * stride;
但是我不确定这是否是实现目标的最佳方法。
非常感谢对此@tzickel进行的额外调试,这是非常深入的调试, @kippr我有一个问题,您提到这是在Mac上全新安装的pip,因此不应该从头开始构建吗? 另外,如果我使用gcc在Linux系统上运行:
$蟒蛇
Python 3.6.5(默认,2018年4月1日,15:40:54)
Linux上的[GCC 7.3.0]
键入“帮助”,“版权”,“信用”或“许可证”以获取更多信息。
将numpy导入为np
np.version.version
'1.14.2'
np.min([1。,2.,3.,4.,np.nan])
南
np.min([1。,2.,3.,np.nan,4.])
南
np.min([1。,2.,np.nan,3.,4.])
南
np.min([1。,np.nan,2.,3.,4.])
南
np.min([np.nan,1.,2.,3.,4.])
南
np.min([np.nan,1.])
南
np.min([np.nan,1.,np.nan])
南
np.min([1。,np.nan])
南
np.seterr(all ='raise')
{'divide':'warn','over':'warn','under':'ignore','invalid':'warn'}
np.min([np.nan,1.0])
南
并且根本看不到任何警告,因此也许如前所述,c铛可能是问题所在。 唯一让我感到奇怪的是,为什么您通过pip install numpy看到了这一点。 它是如何建造的? 以及使用了哪些标志?
我的mac也没有错误:
我想知道是否可以通过以下方式使它更安全
if (c1 = n_mm_min_pd(c1, c2), py_get_floatstatus() & NPY_FPE_INVALID) {
@juliantaylor有想法吗?
甚至
return_nan = (c1 = n_mm_min_pd(c1, c2), py_get_floatstatus() & NPY_FPE_INVALID);
if (return_nan) {
尽管可能不是线程安全的,但逗号运算符应该是一个序列点。 嗯,我想知道simd代码中有多少
@VictorRodriguez如果我使用python2.7在我的Mac上运行pip install numpy,它将从源代码构建。 如果我使用python3运行pip install,它将通过轮子安装。
我捕获了pip安装的完整输出: https :
为了测试上面的更改,我从源代码(当前的主服务器)构建,但是检查了一下,我仍然没有发现损坏的行为。 构建时,我使用了INSTALL.rst.txt中建议的命令行:
python setup.py build -j 4 install --prefix $HOME/.local
请注意,这里有人说他也已经在Windows中看到该bug。 我认为它不是在Windows上用clang编译的,而是MSVC或GCC编译的,这可能意味着numpy不遵守平台规则。 在Windows中,numpy使用_statusfp获取fp状态,MSDN文档指出:
许多数学库函数会修改浮点状态字,结果无法预测。 优化可以对_status87,_statusfp和相关函数的调用进行重新排序,合并和消除浮点运算。 使用/ Od(禁用(调试))编译器选项或fenv_access pragma指令可防止优化对浮点运算进行重新排序。
GCC和MSVC(但现在还不是clang)具有实用性来控制它。
@tzickel确信Windows版本表示它与cygwin有关。 MSVC不会为我复制它。
总的来说,我喜欢@charris的建议,它是标准C,不需要编译指示,并且AFAICT不会增加任何开销
/* use the comma operator to prevent optimization changing the order of evaluation */
if (c1 = n_mm_min_pd(c1, c2), py_get_floatstatus() & NPY_FPE_INVALID) {
即使用于python 2.7的visual studio 8编译器也支持
第二个更紧凑的建议似乎太模糊了
代码中是否还有其他地方容易受到此错误的影响?
cygwin版本表示GCC,这意味着该错误应像linux一样起作用?
如果我正确理解,则逗号运算符不会帮助您进行优化,它可以在代码生成的另一个层次上工作。 编译器仍然可以自由地认为这两个表达式无关,并且可以随意移动它们。 这是一个小例子,说明是这种情况(尝试使用其旁边的行更改注释代码),检查与调用外部函数有关的minpd(确保在编译器标志中给出了-O3),然后在GCC和CLANG(似乎GCC主干目前具有相同的错误:)):
如果您查看fenv.h,则访问该文件的代码中的每个函数基本上都具有相同的潜在问题。 因此,在numpy / core / src / npymath / ieee754.c中使用的代码中正在调用的所有内容
我认为,clang当前无法通过优化为此类函数生成安全的代码,因此选项为:
A.用gcc编译(至少使用官方的mac wheel),如果用clang编译,则产生警告。
B. Clang支持每个函数的optnone属性,如果使用clang编译,则可以将其撒在此类函数上以禁用所有优化(慢速但正确的代码):
https://clang.llvm.org/docs/AttributeReference.html#optnone -clang-optnone-clang-optnone
切换到逗号运算符根本没有帮助- ;
已经是一个序列点。
@ eric-wieser您确定吗? 我没有看到;
被列为序列点。 https://msdn.microsoft.com/zh-CN/library/azk8zbxd.aspx 。
在任何情况下,都保证逗号运算符的参数的求值顺序是保证的,而用;
分隔的语句则不是这种情况。
@charris不幸的是,建议的更改似乎无法解决问题:
diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src
index 2241414ac..8345e3ef7 100644
--- a/numpy/core/src/umath/simd.inc.src
+++ b/numpy/core/src/umath/simd.inc.src
@@ -1038,9 +1038,8 @@ sse2_@kind@_@TYPE@(@type@ * ip, @type@ * op, const npy_intp n)
c1 = @vpre@_@VOP@_@vsuf@(c1, v1);
c2 = @vpre@_@VOP@_@vsuf@(c2, v2);
}
- c1 = @vpre@_@VOP@_@vsuf@(c1, c2);
- if (npy_get_floatstatus() & NPY_FPE_INVALID) {
+ if (c1 = @vpre@_@VOP@_@vsuf@(c1, c2), npy_get_floatstatus() & NPY_FPE_INVALID) {
*op = @nan@;
}
else {
注意,将变量标记为volatile确实可以解决该问题。
如果您想尝试其他变体,请告诉我。
似乎编译器没有遵守有关逗号运算符的规范,至少在我们了解规范的情况下。 对于编译器当前状态,最简单的解决方案似乎是添加volatile
,尽管它看起来很脆弱。
好吧,GCC 8.1刚刚发布,您猜怎么着...具有优化功能的GCC现在产生的问题与clang在此处的相同问题https://github.com/numpy/numpy/issues/10370#issuecomment -384154230可以按预期提供帮助,但volatile可以提供帮助),尽管我不知道distutils是否在gcc标志中启用了缓解这种情况的功能,但我认为不会。
这是GCC 8.1上的代码(可以与7.3进行比较):
https://godbolt.org/g/AJRdRQ
在asm中搜索minpd和npy_get_floatstatus调用。
暂时让我们与volatile一起进行一些测试,这些测试有望在出现问题时发出信号。 我们可能会看到的另一种选择是一个单独的函数,可以在其中使用volatile或编译器指令,但将其放在一个位置以使其易于管理。
比这个特定问题要大得多。 调用ieee754.c中的函数的所有numpy代码都必须进行审核和修复。 (也许再次重命名此问题,或者更好的是,打开一个新问题)。
minpd指令的令人惊讶的行为可能与https://github.com/numpy/numpy/issues/10370#issuecomment -381241813有关:
如果该指令的NaN(SNaN或QNaN)只有一个值,则将第二个操作数(源操作数),即NaN或有效的浮点值写入结果中。
参见: http :
@mattkretz似乎并非如此。 (这是预期的行为,以及为何已进行此检查的原因)。
@tzickel出于好奇,问题出现在哪个优化级别? 我们曾经将自己限制为-O2
,但是我认为某些平台一直在使用-O3
或同等水平。
类似于此gcc错误,我认为: https :
似乎在这里设置#pragma STDC FENV_ACCESS ON
是正确的解决方案,但是它确实需要C99,我们需要删除python 2.7才能使用。 也许GCC --std=c90
模式假设它可以进行优化,因为缺少实用性
对于您所有的问题,只需转到此处的链接:
https://godbolt.org/g/AJRdRQ(*它似乎是共享的,因此可以将输入内容复制到新窗口中)
并尝试更改编译器版本,编译器标志和代码,并即时查看结果...
在两个最新的编译器上甚至使用-O1时,都会发生这种情况。 #pragma似乎没有任何作用。
该版本非常复杂,汇编程序太多,很难将汇编程序与c代码关联。 原始版本要简单得多,并且可以解决该问题。
另见公关
嗯...。有人可以告诉我在哪个OS /编译器上编译了numpy-1.14.3-cp27-cp27mu-manylinux1_x86_64.whl(来自pypi档案)吗? 我认为这里也可能存在另一个(相关)问题。
@tzickel我相信默认的ubuntu可信编译器是gcc 4.8,我看不到已安装了最新的东西。
@charris manylinux容器在安装了gcc 4.2的情况下运行Centos5。
@ngoldbaum感谢您的信息。 我们将需要尽快为Python 3.7构建轮子。 就像在travis.yml构建矩阵中添加MB_PYTHON_VERSION=3.7
条目一样容易吗?
我认为您需要等到manylinux工具得到更新。 在python3.6发布IIRC之后花了几周的时间。 @njsmith可能知道更多。
@ngoldbaum是什么促使gcc 4.2
? 如果我们愿意,使用更高版本的编译器是否容易?
是什么推动了gcc 4.2的选择?
我相信目标是启用足够老的glibc进行编译,以使二进制兼容性问题在实践中不会成为问题
如果我们愿意,使用更高版本的编译器是否容易?
我不知道。 我也不知道numpy如何管理建筑轮子。 我正在为我的项目使用Matthew Brett的multibuild项目,我需要等到更新后为我的项目构建python3.7轮子。
好的,不确定这是否是最终的相关问题,但是我想我在该SSE代码中发现了另一个问题:
在numpy 1.14.0中,添加了一些代码,以在出现FP错误时抛出运行时警告:
https://github.com/numpy/numpy/commit/d47ca7b26172c42b01c3132d0e46e70578c8ea21
但是,如果我们再次查看SSE实施:
https://github.com/numpy/numpy/blob/d7d5cb3feccc1fc6cf57159e8b9fe0a733968706/numpy/core/src/umath/simd.inc.src#L1020
我们可以看到,它仅通过阵列的中间对齐部分通过了FPU,而头和尾(它们不是SSEable,因为它们不是内存对齐的)是手动检查的,而不是通过FPU,而SSE部分会触发,因此只有中间部分会触发NaN警告,而另一部分(在输入和输出相等时)不会触发。 那样行吗 ?
np.min([1,np.nan,1,1,1,1,1,1])不会触发运行时警告
但是np.min([1,1,np.nan,1,1,1,1,1])可以。
np.min([1,np.nan,1,1,1,1,1,1])不会触发运行时警告
@tzickel这与#11029有关,对吗?
编辑:格式化
似乎问题出在#8954,导致PR#9020
是的,但我的意思是,#9020并未涵盖所有可能的情况。 其中之一就是该SSE代码(它颠覆了该机制以进行一些优化)。
至于#11029,我想弄清楚为什么在这里和那里的帖子中,除了NaN传播错误外,有时还会显示警告,有时却不显示
另一个问题是,如果输入中同时存在NaN是min / max两者的结果,并且我们已经检查了isNan / valid,那么在发现NaN的第一个实例时是否应该快速退出?
@tzickel还原操作均未提前退出。 如果将来将它们重构为gufuncs,它们可能会出现。