Numpy: تحذير من قبل np.float 32 .__ mul__

تم إنشاؤها على ٢٧ أبريل ٢٠١٧  ·  53تعليقات  ·  مصدر: numpy/numpy

في Sagemath واجهنا في بطاقتنا # 22799

RuntimeWarning: invalid value encountered in multiply

أثناء ضرب numpy.float32 ببيانات غير عددية ؛ على سبيل المثال ، يجب أن يفشل numpy في إجراء عملية الضرب هذه بصمت ، وهو ما يحدث بالفعل إذا تم البناء باستخدام gcc ، أو إذا كان بدلاً من np.float32 هو np.float أو np.float128 .

بتعبير أدق ، يحصل المرء على تحذير من مكالمة Python

type(numpy.float32('1.5')).__mul__(numpy.float32('1.5'), x)

حيث x هو متعدد حدود Sagemath أحادي المتغير مع معاملات في نوع RealField الخاص بـ Sagemath. (وهذا النوع المعين فقط من البيانات هو الذي يطلق هذا).
وهذا يعني أنه من المحتمل أن تنطلق مثل هذه التحذيرات التي لا معنى لها خارج Sagemath ؛ يمكننا إعادة إنتاجه على OSX 11.12 مع مخزونه cc (بعض مشتقات clang 3.8) ، وكذلك على Linux مع clang 4.0 وعلى FreeBSD 11.0 مع clang 4.0 أو clang 3.7.

من المحتمل أن نكون قادرين على إنتاج طريقة لإعادة إنتاج هذا خارج Sagemath ، على الرغم من أننا نحتاج إلى بعض النصائح حيث يتم تنفيذ هذا __mul__ في الكود الرقمي ، لمعرفة الوظائف المطبقة على x ...

نلاحظ هذا في numpy 1.11 و 1.12 أيضًا.

ال 53 كومينتر

نفس الصورة مع numpy.float32('1.5').__mul__(x) بالإضافة إلى __add__ و __sub__ .

هذا النوع من الخطأ نموذجي للمصفوفات التي تحتوي على nan أو infinity . ماذا يعود np.array(x) ؟

@ eric-wieser: إرجاع array(x, dtype=object) ، بدون تحذيرات.

هل يعطي np.multiply(np.float32('1.5'), x) نفس التحذير؟

يعطي numpy.multiply(numpy.float32('1.5'), x) نفس التحذير.

ماذا عن type(x).__rmul__(numpy.float32('1.5'), x) ؟

أيضًا ، إذا كان بإمكانك تشغيل warnings.filterwarnings('error') ، فستحصل على تتبع مكدس كامل

type(x).__rmul__(numpy.float32('1.5'), x)

TypeError: descriptor '__rmul__' requires a 'sage.structure.element.Element' object but received a 'numpy.float32'

يمر x.__rmul__(numpy.float32('1.5')) ما يرام.

يبدو أنني نسيت كيف يعمل rmul . قصدت type(x).__rmul__(x, numpy.float32('1.5')) ، لكنني أتخيل أن هذا يفعل نفس الشيء مثل x.__rmul__ ، ما لم يكن x غريبًا حقًا

هل هذا أيضا فشل؟ np.multiply(np.array(1.5, dtype=object), x) (هذه المرة مع filterwarnings ، من فضلك)

يمر type(x).__rmul__(x,numpy.float32('1.5')) بدون سابق إنذار.

وبالمناسبة ، إعداد warnings.filterwarnings('error') لا يمنحني أي شيء مثير للاهتمام ،

---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-50-b3ece847d318> in <module>()
sage: np.multiply(np.array(1.5, dtype=object), x)
---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-52-706823a0b5a2> in <module>()
----> 1  np.multiply(np.array(RealNumber('1.5'), dtype=object), x)

RuntimeWarning: invalid value encountered in multiply

حسنًا ، فعلت حكيم شيئًا لم أكن أتوقعه هناك. نفس السلوك مع float('1.5') رغم ذلك ، أعتقد؟

حسنًا ، هذا ما أعتقد أنه يحدث:

  • يستخدم numpy بشكل صحيح حلقة الكائن في ufunc ، والتي تنتهي باستدعاء PyNumber_Multiply
  • داخل sage ، هناك شيء ما يقوم بتعيين علامة الخطأ في FPU (خطأ في sage؟)
  • numpy بفحص علامة fpu العادية عند الخروج من ufunc (خطأ في حلقات الكائن؟) ، والعثور على الخطأ الذي تركه بمقدار sage
sage: float(1.5).__mul__(x)
NotImplemented
sage: np.float(1.5).__mul__(x)
NotImplemented
sage: np.float32(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x
sage: np.float64(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

تجدر الإشارة إلى أن np.float is float لأسباب تتعلق بالتوافق

لماذا لا يعود NotImplemented np.float32(1.5).__mul__(x) NotImplemented ؟

لأنه يعرف أنه يمكنه التعامل معها كـ np.multiply باستخدام حلقة كائن ، ثم حاول مرة أخرى باستخدام float * x داخل تلك الحلقة. لسوء الحظ ، يلتقط الغلاف حول تلك الحلقة أعلام FPU التي حددها sage.

إذا نظرت عن كثب ، ستجد أنه لا يزال يتم استدعاء x.__rmul__ بشكل أعمق في المكدس

sage: np.float32(1.5)*x
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x
sage: np.float128(1.5)*x
1.50000000000000*x
sage: np.float64(1.5)*x
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

لذلك يبدو كما لو أن np.float128 لا بأس به ، لكن

sage: np.float128(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

هذا غريب. ربما يكون هناك خطأ في المترجم (كما لا نراه أبدًا في دول مجلس التعاون الخليجي) ، ولكن في أي مكان؟

يتم تعيين علامة FPU لسبب ما على clang ولكن ليس gcc داخل الكود الحكيم ، على ما يبدو. يقع اللوم على Numpy في إحداث ضجيج حوله ، لكنني أشك بشدة في أنه يقع اللوم على وضعه في المقام الأول.

لسوء الحظ ، لا يكشف numpy أي طريقة لطلب إشارات FPU صراحة - سيكون ذلك مفيدًا جدًا لتقسيم المشكلة داخل حكيم.

أفترض أن هذا يسبب نفس التحذير (يحتاج إلى رقم 1.12 للقيام بذلك ، على ما أعتقد)

mul = np.vectorize(x.__rmul__)
mul(float('1.5'))

ليس متشابهًا تمامًا ، ولكنه قريب:

/usr/home/dima/Sage/sage/local/lib/python2.7/site-packages/numpy/lib/function_base.py:2652: RuntimeWarning: invalid value encountered in __rmul__ (vectorized)
  outputs = ufunc(*inputs)
array(1.50000000000000*x, dtype=object)

حسنًا ، جيد ، يبدو أن هذا يشير إلى أنه لا يوجد شيء محدد مع np.float32 أو np.float64 ، إنها آلية أكثر عمومية لإنشاء تحذيرات تبدأ هنا.

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

نعم ، هذا يؤكد شكوكي ويوفر لك طريقة لتصحيح الأخطاء. هذا الرمز

def check_fpu(f):
    @functools.wraps(f)
    def wrapped(*args, **kwargs):
        excluded = list(range(len(args))) + list(kwargs.keys())
        fvec = np.vectorize(f, excluded=excluded)
        return fvec(*args, **kwargs)
    return wrapped

عند تطبيقه على دالة Python ، يسمح لك بعزل التحذيرات داخل هذا الجزء من التعليمات البرمجية.

أعني ، من الغريب أن يحدث ذلك على الإطلاق ؛ لا يخترع المترجمون عادة NaNs ثم يرمونها دون سبب.

إذا كنت تحاول تعقبه ، فمن المحتمل أن تنظر إلى الكود الموجود في الحكيم الذي ينفذ الضرب لتلك كثيرة الحدود - من المحتمل أن يكون إعداد العلم الغريب يحدث طوال الوقت ، ومشاركة numpy الوحيدة هي جعل ذلك مرئيًا .

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

check_fpu() به خطأ إملائي ، يجب أن يكون هناك fvec = np.vectorize(f, excluded=exclude) .
ونحن في python2: import functools32 as functools .

لا يحتاج functools.wraps إلى Python 3 ، أليس كذلك؟

أحصل على خطأ إذا استخدمت functools في python2 ، في setattr() call

AttributeError: 'method-wrapper' object has no attribute '__module__'

نعم ، أظن أنه مهما كانت مكتبة متعددة الدقة تنفذ العمليات الحسابية للمعاملات في RealField التي تقوم بتعيين علامة FPU. هل المكتبات الأساسية مجمعة مع نفس مترجم numpy في كل من الظروف المختلفة؟ أم يتم إعادة بناء numpy فقط مع المجمعين المختلفين؟

نعم ، أعتقد أنها أيا كانت مكتبة متعددة الدقة تنفذ العمليات الحسابية للمعاملات في RealField

هذا MPFR للتسجيل.

نحاول نقل Sagemath إلى clang + gfortran (في الغالب على OSX و FreeBSD ، الأنظمة الأساسية حيث يكون clang هو المترجم الأساسي) ، بحيث يكون بناءه وتشغيله على OSX أسهل وأسرع (FreeBSD هو أكثر من أداة للحصول على بيئة مماثلة بدون متاعب أجهزة OSX و Apple).

جميع المقارنات التي أبلغ عنها هنا مخصصة للبنيات الكاملة باستخدام clang / clang +++ gfortran بدلاً من gcc / g +++ gfortran.

يبدو أن الغلاف يخبرنا أن x.__rmul__ يقوم بإعداد علامة FPU

check_fpu(x.__rmul__)(np.float32('1.5'))

يطبع التحذير ، بينما لا يطبع x.__rmul__(np.float32('1.5')) .

في الواقع - كنت أفترض أن x.__rmul__ تمت كتابته بلغة Python ، وأنه يمكن تقسيم كود المصدر الخاص به للعثور على البت الذي يحدد العلامة تحديدًا

x.__rmul__ موجود في Cython ، لكنه لا يزال جزءًا صغيرًا من التعليمات البرمجية للتحقيق فيه.

إذا كانت هناك طريقة بسيطة لتغيير التحذير إلى خطأ ، فستحصل على تتبع (ينشئ Cython عمليات تتبع للأخطاء ولكن ليس للتحذيرات).

jdemeyer IMHO تحذير numpy يصدر لاحقًا في مسار الكود ، أي أنه نتيجة فحص صريح لعلامات FPU ، وليس مجموعة مقاطعة.

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

jdemeyer هل كود Cython بين sig_on() / sig_off() من cysignals يطرح استثناءً إذا تم رفع علم FPU؟ أم أنها تعتمد على العلم؟

قد تطرح cysignals استثناءً وهو SIGFPE يتم رفعه ، والذي قد يحدث إذا تم رفع علامة FPU ، اعتمادًا على تكوين FPU. لكنها لا تفعل ذلك بشكل افتراضي.

تحذير مشابه: RuntimeWarning: invalid value encountered in greater هو
قادمة من np.float64(5)>e . هنا e هو ثابت Sagemath الذي يحدد أساس اللوغاريتم الطبيعي 2.71828 ... وهكذا في طريق تقييم هذا إلى True يجب أن يتم "تحويله" (بالتأكيد ، e "يعرف "تقريبه العددي ، إنه e.n() ) لرقم.
هذا التقريب من النوع RealField المذكور أعلاه (لذلك ربما يكون هذا التحذير وثيق الصلة).

مرة أخرى ، السؤال هو: ما الذي يفعله numpy لتقييم np.float64(5)>e ؟
أو بالمقابل ، ينبثق نفس التحذير من np.float64(5).__gt__(e) ، لذلك يمكن للمرء أيضًا البدء من هناك.

لاحظ أن type(e) هو sage.symbolic.constants_c.E ؛ إنها في الأساس فئة وهمية (تقريبًا)
تغليف تعبيرات ساجيماث الرمزية ( SR ).

لا توجد تحذيرات من np.float64(5).__gt__(e.n()) أو np.float64(5)>e.n() .
يحدث نفس الشيء (نفس نمط التحذير / عدم التحذير) إذا استبدلت e بـ pi (مع pi.n()==3.1.415... ).
pi النوع SR ، أي sage.symbolic.expression.Expression .

الجواب هو نفسه هنا - numpy يستدعي np.greater بحلقة كائن. في المستوى السفلي ، هذا يستدعي e.__lt__(5.0) . ولكن مرة أخرى ، يتحقق من أعلام FPU قبل وبعد ، ويلاحظ أن هناك شيئًا ما غير صحيح.

تفوض معظم العمليات الحسابية / المنطقية ndarray (باستثناء - و divmod ) إلى ufuncs. عندما يتم استدعاؤها باستخدام كائنات sage ، فإن هذا سيستدعي حلقات O (كائن) لهذه ufuncs. سوف تدور حلقات الكائن هذه على المصفوفة (التي تكون في هذه الحالة 0d) ، وتقوم بتشغيل عامل python العادي على العناصر ، ولكن تحقق من وجود إشارات FPU عندما تفعل ذلك.

مرة أخرى ، يضع الحكيم هذه الأعلام. ربما تكون هذه علامة على وجود خلل ، وربما لا.

أعتقد أن هناك حجة جيدة هنا مفادها أن numpy لا ينبغي أن يتحقق من أعلام fpu لهذه الحالات. njsmith ، هل تعتقد أنه يجب علينا المضي قدمًا في إزالة التحقق من أنواع الكائنات؟

في واقع الأمر ، فإن e.__lt__(5.0) تعبير رمزي:

sage: type(e.__lt__(np.float32(5.0)))
<type 'sage.symbolic.expression.Expression'>
sage: e.__lt__(np.float32(5.0))
e < 5.0
sage: bool(e.__lt__(np.float32(5.0)))  # this is how it's evaluated
True

وبالتالي أشك حقًا في أنه تم استدعاؤه في النهاية ، حيث يحصل المرء على True . أيضًا ، غلاف غلاف check_fpu من أعلى لا يجعله يطبع التحذيرات ، أي ما يلي يعمل فقط.

sage: check_fpu(e.__lt__)(np.float32(5.0))
e < 5.0

لقد تمكنت من تثبيت مشكلتنا في Sagemath وصولاً إلى امتداد C معين باستخدام وحدة fpectl Python (التي تم كسرها إلى حد ما ، ولكن ليس تمامًا ، على FreeBSD). لقد كان سريعًا جدًا في الواقع بمجرد أن تمكنت من تثبيته.

IMHO fpectl مفيد جدًا بحيث يجب إصلاحه ؛ ربما تستخدم حتى في numpy بدلاً من ، أو بالإضافة إلى ، np.seterr() ، لأنها توفر دقة أفضل للمكونات المترجمة.

الفرق بين نهج fpectl و np.seterr هو:

np.seterr بتشغيل حلقة ufunc ، ثم يتحقق لمعرفة ما إذا تم تعيين أي إشارات.

fpectl ببعض السحر لتحقيقه بحيث أنه كلما حدثت عملية تؤدي إلى تعيين إحدى العلامات ، يقوم الجهاز بإثارة مقاطعة ، وتحول kernel هذا إلى SIGFPE يتم تسليمه إلى العملية ، ويقوم بتثبيت معالج SIGFPE الذي يخرج مباشرة من معالج الإشارة longjmp s إلى رمز معالجة الخطأ.

بعض الجوانب السلبية للنهج fpectl هي: (أ) لا يعمل على الإطلاق على Windows ، (ب) أنه يكسر الكود الذي يتسبب داخليًا في تعيين إحدى هذه العلامات مؤقتًا ثم مسحها (هذا هو قانوني وأتوقع أن هناك libm يفعل ذلك) ، (c) longjmp هش بشكل لا يصدق ؛ في الأساس ، أنت تخاطر بحدوث مشكلة في كل مرة تقوم فيها بذلك. بالتأكيد لا يمكن أن يكون حلاً عامًا للأشكال التعسفية التي يحددها المستخدم.

بالنظر إلى كل هذا ، لا أعتقد أن numpy سيتحول.

على أي حال ، يبدو أن المشكلة الأصلية قد تم حلها ، لذا أغلق هذا - لا تتردد في فتح مشكلة جديدة إذا كنت تريد إجراء تغييرات في seterr .

على أي حال ، يبدو أنه تم حل المشكلة الأصلية

هل نحن على يقين من أننا لا نريد تعطيل التحقق من علامات FPU لحلقات الكائن؟ قد يبدو هذا تغييرًا معقولًا إلى حد كبير.

@ إيريك وايزر: أوه ، هذه فكرة مثيرة للاهتمام ، نعم. ربما يستحق الأمر فتح مشكلة لذلك :-). ومع ذلك ، فإن "الشيء الصحيح" معقد جدًا - من الناحية المثالية لا ينبغي أن نضع غلافًا خاصًا لنوع الكائن (أعتقد أن نوع المستخدم) ، كما يجب ألا تستخدمه حلقات الأعداد الصحيحة أيضًا (قد يكون هذا تحسينًا حقيقيًا في بعض البنى حيث يتم التحقق / مسح أعلام FPU بطيء للغاية) ، لكن حلقات الأعداد الصحيحة تحتاج إلى طريقة للإشارة صراحة إلى أخطاء الأعداد الصحيحة ، وهو ما تفعله حاليًا عن طريق تعيين إشارات FPU بشكل صريح ، ... لست متأكدًا من أن هذه حالة يكون فيها انخفاض سهل -تعليق الفاكهة؟

أم أنني أسأت الفهم ، وحكى حكيم فقط المشكلة ، وما زالوا بحاجة إلى تغيير بسيط لإصلاحها بالفعل؟

njsmith : أنا لا أفهم لماذا تقول أنها لن تعمل على Windows. (سيكون هذا صحيحًا في عصر ما قبل C99 ، رغم ذلك). تتوفر وظائف معالجة FPU الحديثة (fenv) بمجرد أن يكون مترجم C متوافقًا مع معيار C99. بصرف النظر عن fenv ، كل ما تحتاجه هو setjmp / longjmp (مرة أخرى ، ميزة C القياسية).

لدي فضول أيضًا لسماع معلومات عن libm يسبب أحد استثناءات FE في سياق العملية العادية.
(ما لم يتم تصنيفها على أنها خطأ).

dimpase : أنت بحاجة أيضًا إلى دعم SIGFPE غير المحدد في C99. (حسنًا ، تقول C99 أنه يجب أن يكون هناك SIGFPE ، ولكن هذا للقسمة على صفر - لا تحدد أي طريقة لتوصيلها باستثناءات النقطة العائمة.) ومع ذلك ، يبدو أنني أخطأت في تذكرها ، وعلى الرغم من أن Windows لا يدعم الإشارات ، يحاكي MSVCRT SIGFPE باستخدام معالجة الاستثناءات المهيكلة ، ويوفر وظيفة _control_fp غير القياسية لتمكينها لاستثناءات fp معينة ، لذا فإن دعم Windows ليس في الواقع عائقًا. OTOH لا يهم كثيرًا نظرًا لأن longjmp لا يحدث بالتأكيد بدون سبب وجيه للغاية :-)

و FWIW ، إذا تسبب libm في استثناء FE ثم مسحه مرة أخرى ، لا يمكنني معرفة سبب اعتبارهم هذا خطأ. لست متأكدًا من وجود أي من هذه التطبيقات ، لكنها معقولة ، وإذا حدث ذلك ، فإن الطريقة التي سنكتشف بها هي b / c يخبرنا أحدهم أن numpy مكسور على النظام الأساسي X وسيكون الإصلاح الوحيد هو التراجع عن التغيير اقترحتم.

هل يمكنكم الرد على السؤال الذي طرحته في نهاية تعليقي السابق؟

njsmith : إذا احتاج libm (أو أي رمز مستخدم آخر) إلى التسبب في استثناء FE ومعالجته ، فسيقوم بإعداد معالج استثناء FE الخاص به ، وحفظ المعالج السابق ، واستعادة المعالج السابق عند الخروج.
لذلك لا توجد مشكلة إذا كان الكود الأساسي يعمل وفقًا للقواعد.

فيما يتعلق بدعم MS لهذا ، قاموا بشحن fenv.h منذ Visual C (++) 2013 أو نحو ذلك .
من المفترض على وجه التحديد أن تكون مفيدة مع setjmp / longjmp (كيف يتم ذلك بالضبط تحت غطاء المحرك يجب ألا يقلق المرء كثيرًا ، كما آمل).

بخصوص وقت تشغيل Numpy's - تحذير:

  • إذا كنت تعتقد أن رمز المستخدم يمكن أن يعمل بسرعة وبسرعة مع علامات FP ، فيجب أن تكون هذه التحذيرات اختيارية على الأكثر.
  • بخلاف ذلك ، يمكن الاحتفاظ بها بشكل قياسي ، ولكن على الأقل وسيلة للوصول إلى قاع المكان الذي يأتون منه أمر بالغ الأهمية بالنسبة لهم ؛ (محسّن) fpectl طريقة سريعة لتحقيق الأخير. يعد استخدام الأدوات الخارجية (مثل أدوات تصحيح الأخطاء التي تسمح لك بأداة الكود لفحص شيء ما بعد كل تعليمات) أصعب وأبطأ وأكثر عرضة للخطأ - على سبيل المثال ، ليس من غير المعتاد أن يظهر الخطأ فقط على ثنائي محسن ، و يختفي بمجرد محاولة العثور عليه في ثنائي قابل للتصحيح جيدًا.
  • في أي حال ، يجب أن يكون من الممكن إيقاف تشغيل أمر RuntimeWarning.

بخصوص هذه المشكلة في Sage - لا يزال الإصلاح (نأمل أن يقتصر على بعض المشكلات في MPFR فقط).

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

إذا احتاج libm (أو أي رمز مستخدم آخر) إلى التسبب في استثناء FE ومعالجته ، فسيقوم بإعداد معالج استثناء FE الخاص به ، مع حفظ المعالج السابق ،

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

فيما يتعلق بدعم MS لهذا ، قاموا بشحن fenv.h منذ Visual C (++) 2013 أو نحو ذلك.
من المفترض تحديدًا أن تكون مفيدة مع setjmp / longjmp

لا أستطيع معرفة ما تتحدث عنه هنا. Afaict ، الوظيفة القياسية في fenv.h مفيدة فقط لتنفيذ وظائف النمط الخالي ، وتلتزم MS بالمعيار. لا أرى أي وظائف هناك يمكن استخدامها مع setjmp / longjmp على الإطلاق.

يمكن تشغيل رمز المستخدم بسرعة وبسرعة مع أعلام FP ، ثم يجب أن تكون هذه التحذيرات اختيارية على الأكثر.

إن مسح العلم الذي تم تعيينه بواسطة حساب وسيط بعناية هو عكس اللعب السريع والمرخي معهم. أيضا ، التحذيرات اختيارية.

طريقة الوصول إلى أسفل المكان الذي يأتون منه أمر بالغ الأهمية بالنسبة لهم ؛ (محسّن) fpectl طريقة سريعة لتحقيق هذا الأخير.

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

إذا حدث هذا مرة أخرى ، فما عليك فعله هو إجراء مكالمة C واحدة لتمكين SIGFPE ، ثم استخدام مصحح أخطاء للحصول على تتبع مكدس. لا تحتاج إلى بناء تصحيح للحصول على تتبع مكدس ؛ كل ما عليك فعله هو عدم تجريد الرموز. ويا ، نحن نعلم الآن في حالة ظهور هذا مرة أخرى.

أتفهم أن هذا كان محبطًا حقًا لتصحيح الأخطاء ، لكن ليس من المفيد الإصرار على أن المشاريع الأخرى تحتاج إلى تغيير أو صيانة البنية التحتية الأساسية عندما لا يمكنك حتى شرح ما سيحققه ذلك بوضوح. (ليس لدي أي فكرة عن كيفية اعتقادك أن تغيير شيء ما هنا قد يساعدك في العثور على هذا النوع من الأخطاء بشكل أسرع - الفكرة الكاملة لـ longjmp هي تدمير المعلومات الأكثر دقة التي تقول أنك تريدها.)

أخيرًا ، اتضح أنه يتلخص في خطأ طويل الأمد في مترجم clang C. بشكل أساسي ، في نطاق معين من double تكون مهمة كما في

unsigned long a;
double b;
...
a = b;

يرفع FE_INVALID (وأحيانًا FE_INEXACT ) ؛ راجع للشغل هذا يؤثر أيضًا على أنواع أخرى من البيانات العائمة. كبيرة MPFR (MPFR يجب أن تنسخ المضاعفات في عواماتها التعسفية الدقيقة ، بالتأكيد) قدم الناس حلًا بديلًا ، مع إصلاح هذا للحكيم.

بالمناسبة ، هناك علاقة طويلة الأمد (منذ عام 2010 ، مع عشرات التكرارات المغلقة) تقول علة 8100 أنه لا يوجد أمل في استخدام Clang fenv.h لجني fpectl يعمل بشكل صحيح في الوقت الحالي . Clang ليست متوافقة تمامًا مع C99 في هذا الصدد ، وتخجل حقًا من ذلك.

لست متأكدًا مما إذا كان numpy يريد فعل أي شيء حيال ذلك ؛ قد يكون من المفيد ملاحظة أن RuntimeWarning قد يكون فقط بسبب خطأ في المترجم (نقلاً عن "clang bug 8100" ، وهو مثال بارز جدًا).

الخطأ 8100 غير مناسب ؛ هذا لـ C99 pragmas لتعطيل تحسينات النقطة العائمة ، ولا يدعمها أي مترجمين سائدين. يبدو أن numpy (في الغالب) يعمل على أي حال :-)

تتمثل روح الخطأ 8100 في أن clang لا تهتم بترجمة عمليات FP بشكل صحيح ؛ على الرغم من أن المحامي قد يختلف. :-)

حسنًا ، الخطأ المذكور بالفعل

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