Numpy: BUG: لا يقوم np.min دائمًا بنشر NaNs

تم إنشاؤها على ١١ يناير ٢٠١٨  ·  65تعليقات  ·  مصدر: numpy/numpy

ينشأ هذا التحقيق من scipy CI التي بدأت بالفشل على appveyor في الأيام القليلة الماضية ، أي بعد إصدار 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 ، 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

مع المجموعة الأولى من أمثلة التعليمات البرمجية ، لماذا لا ينتج عن الأمثلة الثلاثة الأولى تحذير ، فقط الأخير؟
مع المجموعة الثانية من الأمثلة ، لم يتم إصدار أي تحذير على الإطلاق.

00 - Bug numpy.core

ال 65 كومينتر

xref scipy / scipy # 8282 ، scipy / scipy # 8279

أعتقد أن هناك نقطة أخرى هنا وهي أنه قد تكون مسارات كود مختلفة تؤدي إلى سلوك مختلف (ليس خاطئًا حقًا على ما أعتقد) ، على سبيل المثال بسبب استخدام AVX أو ما شابه ، أعتقد أنني رأيت أحيانًا أن العناصر المتجهة فشلت في تعيين إشارات وحدة المعالجة المركزية للخطأ ، و نظرًا لأن ذلك قد يظهر عشوائيًا بعض الشيء إذا تم استخدامه أم لا ...

إذا كان هذا له علاقة كبيرة به ، لكنني أتوقع ذلك ، فإن numpy لا يفعل الكثير بشأن أخطاء الفاصلة العائمة عادةً على ما أعتقد. باستثناء التحقق من حدوث شيء ما.

وكما قال تشاك ، فإن الكثير من علامة خطأ النقطة العائمة تختلف باختلاف الأنظمة للأسف.

حسنًا ، فهمت سبب حدوث الخطأ فقط في بعض عمليات التثبيت وليس غيرها.
السبب وراء استخدام scipy لـ np.min على مصفوفة ربما تحتوي على NaN هو أنها طريقة سريعة للتحقق من وجودهم. تشير الوثائق غير المفككة إلى أن هذا مسموح به:

يتم نشر قيم NaN ، أي إذا كان عنصر واحد على الأقل هو NaN ، فإن قيمة min المقابلة ستكون 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؟

NotSqrtseberg اراه سلوك مماثل حيث دقيقة لا نشر NaNs لصحيح على الإطلاق، عندما يكون حجم مجموعة المدخلات يحصل على حجم 8:

> 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 .. virtualenv جديدة باستخدام python 2.7.13 و numpy 1.14.2:

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

انظر إلى سطرين "يجب أن يكون هذا نان حسب المستندات: 19.0 " هناك؟

ملحوظة أيضًا لا يظهر التحذير على رقم 1.13.1 (وهو المكان الذي لاحظت فيه هذا السلوك لأول مرة.)

@ kippr من أين لك

سأخمن أن حدود العناصر الثمانية قد تكون مرتبطة بـ AVX512 والمشكلة هي مزيج من المترجم ووحدة المعالجة المركزية. ما هو برنامج التحويل البرمجي / cpus الذي ترى المشكلة فيه؟

juliantaylor خواطر؟

قد يكون للمحاذاة تأثير أيضًا.

مرحبًا charris

شكرا لإلقاء نظرة على رسالتي .. للإجابة على أسئلتك:

وحدة المعالجة المركزية :
❃ sysctl -n machdep.cpu.brand_string Intel (R) Core (TM) i7-6700K CPU @ 4.00 جيجا هرتز

تم تثبيت نمباي من خلال نقطة على بلدي لجنة الهدنة العسكرية في virtualenv جديدة (الثعبان 2.7.13 تثبيتها من خلال البيرة)، لذا أعتقد أنه يستخدم كل مترجم الافتراضي الأعلام وما إلى ذلك؟

لقد قمت للتو بإعادة إنشاء env الظاهري وتثبيت reran 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

شكر
كريس

build.log

ربما لا يكون 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

أنا أستخدم نفس الإصدار numpy (في القوس) مع وحدة المعالجة المركزية التي تحتوي أيضًا على إمكانات AVX2 و sse4.2 ولا أراها على Linux. ربما له علاقة مع mac / clang؟

التحرير / التعديل: (لقد حاولت قليلاً مع إثارة محاذاة مختلفة ، ولم أتحقق من جزء التحذير ، لكن جزء النتيجة الخطأ الذي لا أراه)

أظن أن هناك علامة وحدة المعالجة المركزية لم يتم ضبطها بشكل صحيح ، وربما يتعلق بالمترجم.

يجب أن يكون لدينا اختبار يظهر هذه المشكلة ، حتى لو كان فقط لتتبعها. @ 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 القيم ومحور = 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. يمكننا محاولة إيقاف تشغيل Vectorization على MAC و Windows ومعرفة ما إذا كان ذلك يساعد. هل ترى هذه المشكلة فقط في Python 2.7؟

لا يمكنني رؤية أي شيء في NumPy من شأنه أن يغير هذا السلوك لـ 1.14. ربما يتلاعب OpenBLAS بعناصر التحكم ...

تضمين التغريدة

مرحبًا charris

أرى هذا السلوك أيضًا في Python 3 على جهاز Mac الخاص بي:

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'

ملحوظة: لاحظت هذا السلوك لأول مرة في NumPy الإصدار 1.13 تحت python 2.7 على جهاز Mac الخاص بي ، لذلك لم يكن تراجعًا تم تقديمه في 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'

لكن لا ترى هذه المشكلة في لينكس:

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 لقد رأيت في رحلتي على تحسينات الأداء لنمباي أن openblas والأعلام المترجم يمكن أن تؤثر على سلوك نمباي / scipy (على أساس تجربتي). الخطوة الأولى التي يمكننا اتخاذها هي إجراء اختبار C (باستخدام مكتبات openblas) حتى نتمكن من عزل السلوك ومعرفة ما إذا كان يمكن تكراره. أيضًا لمضاعفة التحقق من هذا فقط على MAC و windows ، أليس كذلك؟ لا يمكنني رؤية هذا السلوك على Linux (fwiw تدخل تصحيحات avx إلى 1.15 ، لذا لا ينبغي أن تؤثر على هذا). @ kippr كيف صنعت numpy في mac / windows؟ مع تحياتي

مرحبًا @ فيكتور رودريغيز

كان هذا عبر تثبيت النقطة على كلا النظامين الأساسيين ، وهو Virtualenv جديد في حالة Mac. انظر أعلاه حيث قمت بلصق سجل النقطة بما في ذلك إخراج التجميع لتثبيت 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

دعنا نلقي نظرة على هذا الرمز على وجه التحديد (قمت تلقائيًا بتوسيع نموذج SSE2) داخل الوظيفة في السطر 1041:

        }
        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) {

وبالفعل ، بمجرد القيام بذلك ، يختفي الخطأ.

(لقد جربت أيضًا مجموعة من النماذج الأخرى الأقل غباءًا لمحاولة جعل المترجم يقوم بتقييم _mm_min_pd قبل عبارة if ، على سبيل المثال عن طريق وضع إشارات إلى c1 على جانبي عبارة if وبعد كتلة if / else ، لا جدوى. أظن أنه إما أعاد ترتيبها على أي حال ولكن دائمًا ما كان يدير مهمة c = _mm_min_pd ، أو كنت أحسب أن مكالماتي كانت في الواقع noops من نموذج أو آخر ..)

ولكن على أي حال يمكنني أن أؤكد أنك حددت الخطأ الذي أراه ، فلنأمل أن يكون لدى شخص ما طريقة جيدة لتلميح المترجم لترك ترتيب _mm_min_pd و npy_get_floatstatus بمفرده ..

حسنًا ، هناك شيء آخر اقترحته Google وقد نجح أيضًا: وضع علامة C1 متقلبة:

https://github.com/numpy/numpy/blob/d7d5cb3feccc1fc6cf57159e8b9fe0a733968706/numpy/core/src/umath/simd.inc.src#L1029

يصبح:

        /* 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 ، لذلك ليس من المفترض أن يبني من الصفر ، أليس كذلك؟ أيضًا إذا قمت بتشغيل نظام Linux الخاص بي مع دول مجلس التعاون الخليجي:

$ بيثون
Python 3.6.5 (افتراضي ، 1 أبريل 2018 ، 15:40:54)
[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 (الكل = "زيادة")
{'divide': 'warn'، 'over': 'warn'، 'under': 'ignore'، 'valid': 'warn'}
np.min ([np.nan، 1.0])
نان

ولا ترى أي تحذيرات على الإطلاق ، لذلك ربما تكون المشكلة كما هو موصوف متعلقة بالرنجة الشيء الوحيد الذي يجعلني أتساءل هو لماذا ترى هذا مع تثبيت النقطة numpy. كيف تم بنائه؟ وما هي الأعلام التي استخدمت؟

أيضًا لا يوجد خطأ في جهاز Mac الخاص بي:

https://hastebin.com/cuzinajero.swift

أتساءل عما إذا كان يمكن جعل هذا أكثر أمانًا بشيء مثل

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 إذا قمت بتشغيل pip install numpy على جهاز mac الخاص بي باستخدام python2.7 ، فسيتم إنشاؤه من المصدر. إذا قمت بتشغيل تثبيت pip باستخدام python3 ، فسيتم تثبيته من عجلة.

لقد التقطت الناتج الكامل لتثبيت النقطة: https://github.com/numpy/numpy/files/1912086/build.log

لاختبار التغييرات أعلاه ، قمت بالبناء من المصدر (الرئيسي الحالي) ، لكنني تحققت من أنه بدون القرص كنت ما زلت أرى السلوك المعطل. عند البناء الذي استخدمت فيه سطر الأوامر المقترح في INSTALL.rst.txt:
python setup.py build -j 4 install --prefix $HOME/.local

كلمة تحذير ، شخص ما هنا يقول إنه رأى الخطأ في النوافذ أيضًا. أفترض أنه لم يتم تجميعه مع clang على النوافذ ، ولكن مع MSVC أو GCC ، قد يعني هذا أن numpy لا يحترم قواعد النظام الأساسي. في windows ، يستخدم numpy _statusfp للحصول على حالة fp ، تنص وثائق MSDN على:

تقوم العديد من وظائف مكتبة الرياضيات بتعديل كلمة حالة الفاصلة العائمة ، مع نتائج غير متوقعة. يمكن أن يعيد التحسين ترتيب عمليات الفاصلة العائمة ودمجها وإزالتها حول استدعاءات _status87 و _statusfp والوظائف ذات الصلة. استخدم خيار المحول البرمجي / Od (Disable (Debug)) أو التوجيه fenv_access pragma لمنع التحسينات التي تعيد ترتيب عمليات الفاصلة العائمة.

دول مجلس التعاون الخليجي و MSVC (ولكن ليس رنة في الوقت الحالي) لديهم براغما للتحكم في هذا.

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) {

وهو مدعوم حتى من قبل مترجم visual studio 8 المستخدم في python 2.7
الاقتراح الثاني الأكثر إحكامًا يبدو غامضًا جدًا

هل هناك أماكن أخرى في الكود معرضة لهذا الخطأ؟

  1. يقول بناء cygwin إن GCC مما يعني أن الخطأ يجب أن يتصرف مثل linux no؟

  2. إذا فهمت بشكل صحيح ، فإن عامل الفاصلة لا يساعد في التحسينات ، فهو يعمل في مستوى آخر من إنشاء الكود. لا يزال المترجم حرا في التفكير في أن كلا التعبيرين غير مرتبطين وأن يحركهما. فيما يلي مثال صغير لإظهار هذه الحالة (حاول تغيير كود التعليقات بالسطر المجاور له) ، تحقق من minpd المتعلق باستدعاء الوظيفة الخارجية (تأكد من إعطاء -O3 في أعلام المترجم) ، وقم بالتبديل بين GCC و CLANG (يبدو أن صندوق GCC لديه نفس الخطأ في الوقت الحالي :)):

https://godbolt.org/g/Zoc5xr

  1. إذا نظرت إلى fenv.h ، فإن كل وظيفة في الكود يمكنها الوصول إلى هذا الملف لها نفس احتمالية حدوث مشكلات. لذلك يتم استخدام كل ما يتم استدعاؤه في الكود من ذلك في numpy / core / src / npymath / ieee754.c

  2. في رأيي ، لا تستطيع clang حاليًا إنتاج رمز آمن لهذا النوع من الوظائف مع التحسينات ، لذا فإن الخيارات هي:
    أ. قم بالتجميع مع دول مجلس التعاون الخليجي (على الأقل عجلات mac الرسمية) ، وقم بإصدار تحذير إذا تم تجميعه باستخدام رنة.
    يدعم Clang خاصية optnone لكل وظيفة ، والتي يمكن رشها على هذه الوظائف لتعطيل جميع التحسينات (رمز أبطأ لكن صحيحًا) إذا تم تجميعها باستخدام clang:
    https://clang.llvm.org/docs/AttributeReference.html#optnone -clang-optnone-clang-optnone

لن يساعد التبديل إلى عامل الفاصلة على الإطلاق - ; هو بالفعل نقطة تسلسل.

@ eric-wieser هل أنت متأكد؟ لا أرى ; مدرجًا كنقطة تسلسل. https://msdn.microsoft.com/en-us/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 ، على الرغم من أنه يبدو هشًا.

حسنًا ، تم إصدار إصدار GCC 8.1 للتو وخمن ماذا ... ينتج مجلس التعاون الخليجي مع التحسينات الآن نفس المشكلة التي تنتجها clang هنا https://github.com/numpy/numpy/issues/10370#issuecomment -384154230 (والفاصلة لا تفعل ذلك المساعدة هناك كما هو متوقع ، لكن التقلبات تفعل) ، على الرغم من أنني لا أعرف ما إذا كانت أدوات التوزيع تمكّن في أعلام دول مجلس التعاون الخليجي التي تخفف من ذلك ، لا أعتقد ذلك.

هذا هو الكود على GCC 8.1 (يمكنك مقارنته بـ 7.3 حيث لا بأس به):
https://godbolt.org/g/AJRdRQ

ابحث هناك عن استدعاء minpd و npy_get_floatstatus في ASM.

دعنا نذهب مع متقلب في الوقت الحالي مع بعض الاختبارات التي نأمل أن تشير إلى وجود مشكلة إذا ظهرت. هناك خيار آخر قد ننظر إليه وهو وظيفة منفصلة حيث يمكننا استخدام التوجيهات المتغيرة أو التوجيهات المترجم ، ولكن لدينا في مكان واحد لتسهيل إدارتها.

هذه قضية أكبر بكثير من هذه القضية المحددة. يجب مراجعة وإصلاح جميع الكودات الرقمية التي تستدعي الوظائف في ieee754.c. (ربما أعد تسمية هذه المشكلة مرة أخرى ، أو الأفضل من ذلك ، افتح مشكلة جديدة).

قد يكون السلوك المفاجئ لتعليمات minpd مناسبًا لـ https://github.com/numpy/numpy/issues/10370#issuecomment -381241813:

إذا كانت هناك قيمة واحدة فقط هي NaN (SNaN أو QNaN) لهذه التعليمات ، يتم كتابة المعامل الثاني (المعامل المصدر) ، إما NaN أو قيمة فاصلة عائمة صالحة ، إلى النتيجة.

انظر: http://www.felixcloutier.com/x86/MINPD.html

mattkretz لا يبدو كذلك. (هذا هو السلوك المتوقع وسبب إجراء هذا الفحص بالفعل).

tzickel بدافع الفضول ، ما هو مستوى التحسين الذي تظهر به المشكلة؟ اعتدنا على تقييد أنفسنا بـ -O2 ، لكنني أعتقد أن بعض الأنظمة الأساسية كانت تستخدم -O3 أو ما يعادله.

على غرار هذا الخطأ في دول مجلس التعاون الخليجي ، أعتقد أن: https://gcc.gnu.org/bugzilla/show_bug.cgi؟id=6065

يبدو أن إعداد #pragma STDC FENV_ACCESS ON هو الحل الصحيح هنا ، لكنه يتطلب C99 ، والذي نحتاج إلى إسقاط python 2.7 لاستخدامه. ربما يفترض وضع GCC --std=c90 أنه بإمكانه إجراء التحسين بسبب غياب البراغما

لجميع أسئلتك ، ما عليك سوى الانتقال إلى الرابط هنا:

https://godbolt.org/g/AJRdRQ (* يبدو أنه مشترك ، لذا انسخ الإدخال إلى نافذة جديدة ربما)

وحاول تغيير إصدار المترجم ، وأعلام المترجم والتعليمات البرمجية ، ورؤية النتيجة بسرعة ...

يحدث هذا عند استخدام زوجي -O1 على كلا المترجمين الأحدث. لا يبدو أن #pragma يفعل أي شيء ....

هذا الإصدار معقد للغاية ، وهناك الكثير من المُجمِّع ومن الصعب ربط المُجمِّع برمز c. كانت النسخة الأصلية أبسط بكثير وأزلت المشكلة أيضًا.

انظر أيضا العلاقات العامة

hmm .... هل يمكن لأي شخص أن يخبرني على أي نظام تشغيل / مترجم كان numpy-1.14.3-cp27-cp27mu-manylinux1_x86_64.whl (من أرشيف pypi) مجمّعًا عليه؟ أعتقد أنه قد تكون هناك مشكلة أخرى (ذات صلة) مخفية هنا أيضًا.

tzickel أعتقد أن مترجم ubuntu

تشغل حاوية manylinuxcharris Centos5 مع تثبيت 4.2 gcc.

ngoldbaum شكرا على المعلومات. سنحتاج إلى بناء عجلات لـ Python 3.7 قريبًا. هل سيكون ذلك سهلاً مثل إضافة إدخال MB_PYTHON_VERSION=3.7 إلى مصفوفة بناء travis.yml؟

أعتقد أنك ستحتاج إلى الانتظار حتى يتم تحديث أدوات manylinux. استغرق ذلك أسابيع قليلة بعد أن خرج python3.6 من IIRC. njsmith ربما يعرف أكثر.

ngoldbaum ما الذي دفع باختيار gcc 4.2 ؟ هل من السهل استخدام إصدار مترجم لاحق إذا أردنا ذلك؟

ما الذي دفع لاختيار دول مجلس التعاون الخليجي 4.2؟

أعتقد أن الهدف كان تمكين التجميع باستخدام glibc القديم بما يكفي بحيث لا تمثل مشكلات التوافق الثنائي مشكلة في الممارسة

هل من السهل استخدام إصدار مترجم لاحق إذا أردنا ذلك؟

لا أدري، لا أعرف. أنا أيضًا لا أعرف كيف يدير numpy عجلات البناء. أنا أستخدم مشروع Matthew Brett متعدد المباني لمشاريعي وسأحتاج إلى الانتظار حتى يتم تحديثه لبناء عجلات 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 لأنها ليست محاذاة للذاكرة) من أجل NaN ولا تمر عبر 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 إذا كان موجودًا في الإدخال ، وقمنا بالفعل بالتحقق من أنه Nan / غير صالح ، ألا يجب عليه الخروج بسرعة عند اكتشاف أول مثيل لـ NaN؟

tzickel أيا من عمليات التخفيض الخروج المبكر. قد يكونون في المستقبل إذا تم إعادة بنائهم ليصبحوا gufuncs.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

inducer picture inducer  ·  3تعليقات

thouis picture thouis  ·  4تعليقات

marcocaccin picture marcocaccin  ·  4تعليقات

keithbriggs picture keithbriggs  ·  3تعليقات

qualiaa picture qualiaa  ·  3تعليقات