Pytorch: RFC: أضف علامة torch.deterministic لفرض الخوارزميات القطعية

تم إنشاؤها على ١٨ ديسمبر ٢٠١٨  ·  67تعليقات  ·  مصدر: pytorch/pytorch

🚀 الميزة

يجب أن نضيف متغيرًا عامًا لإجبار PyTorch على استخدام خوارزميات حتمية بت. يقترح Soumith إضافة العلم إلى حزمة فرعية torch.experimental لأننا لسنا متأكدين من بعض التفاصيل.

تحفيز

أحيانًا تكون الحتمية على مستوى البت بين عمليات التشغيل مفيدة لتصحيح الأخطاء. ومع ذلك ، من الصعب كتابة خوارزميات حتمية فعالة لبعض العمليات.

ملعب كورة قدم

عندما يكون torch.experimental.deterministic هو False (الافتراضي) ، يجب أن تستخدم PyTorch أسرع خوارزمية متاحة لعملية معينة. عندما يكون torch.experimental.deterministic هو True ، يجب أن تستخدم PyTorch فقط الخوارزميات القطعية. يجب أن تصدر PyTorch تحذيرًا إذا لم يكن لدينا خوارزمية حتمية متاحة لعملية معينة وكان torch.experimental.deterministic هو True .

cuDNN

لدينا بالفعل علامة torch.backends.cudnn.deterministic للتحكم في خيارات خوارزمية cuDNN. يجب أن نحتفظ بهذه العلامة في الوقت الحالي ونقصر cuDNN على الطحالب القطعية إذا كان إما torch.backends.cudnn.deterministic أو torch.experimental.deterministic صحيحًا.

غير الأهداف

نحن نهدف فقط إلى الحتمية على مستوى البت بين عمليات التشغيل على الأجهزة التي لها نفس البنية والتكوين. على سبيل المثال ، حتى عندما يكون torch.experimental.deterministic صحيحًا ، فإننا لا نهدف إلى حتمية البت عندما يختلف أي مما يلي:

  • إصدار PyTorch
  • بنية وحدة المعالجة المركزية (مثل x86 مع AVX مقابل ARM)
  • بنية وحدة معالجة الرسومات (مثل AMD مقابل NVIDIA أو P100 مقابل V100)
  • تبعيات المكتبة (مثل OpenBLAS مقابل MKL)
  • عدد خيوط OpenMP

اقتراحات التنفيذ

أقترح إضافة هذه الميزة في خطوتين. الخطوة الأولى هي إضافة علامة torch.backends.cudnn.deterministic وإضافة تحذيرات إلى أي عمليات غير حتمية. الخطوة الثانية هي إضافة تطبيقات حتمية للعمليات غير الحتمية.

توجد قائمة جزئية بالعمليات غير الحتمية في مستندات PyTorch .

أسئلة مفتوحة

كيف يجب أن يتفاعل torch.experimental.deterministic مع بذرة RNG؟ هل يجب تعيين بذرة افتراضية إذا لم يتم تعيين البذور اليدوية؟ هل يجب أن يصدر تحذيرًا إذا لم يتم تعيين البذور اليدوية؟

سم مكعبezyanggchanan @ zou3519

feature high priority determinism internals triaged

التعليق الأكثر فائدة

مرحبًا ، أريد التحدث عن خطة المضي قدمًا مقابل torch.deterministic . هناك بعض الأسئلة عالية المستوى التي نحتاج إلى الإجابة عليها:

  1. ما هي دلالات torch.deterministic ؟ ماذا يتوقع المستخدم؟ هل أفضل جهد مفيد بالفعل للمستخدم؟ إذا لم يكن مفيدا، أنه من الأفضل أن تحدد torch.deterministic من حيث ما العمليات التي تسيطر عليها؟
  2. الآن بعد أن أصبح لدينا علامة torch.deterministic ، فهل من المنطقي إزالة وسيطة الكلمة الرئيسية deterministic= بالكامل من واجهة API العامة ( bmm ، أنا أنظر إليك).
  3. ما هي نهاية اللعبة لهذا العمل؟ ما مقدار ما ستعمل عليه (kurtamohler) ، مقابل المجتمع العام ، وعندما نصل إلى نهاية مهمتك هنا ، كيف تبدو الحالة المعقولة؟

بدءًا من (1) ، تقول التوثيق الحالي لـ torch.deterministic:

     r"""Sets a global flag to force all operations to use a deterministic
    implementation if available. If an operation that does not have a
    deterministic implementation is called while this setting is True, the
    operation will throw a RuntimeError.

    Note that deterministic operations tend to have worse performance than
    non-deterministic operations.

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

يمكننا تغيير توثيق torch.deterministic لتحسين هذا. بعض التغييرات الممكنة:

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

النقطة الثانية تؤدي إلى (2): إذا وجدت torch.deterministic الآن كطريقة لتبديل الحتمية ، فمن الأقل أهمية دعم الحتمية مباشرة في واجهة برمجة تطبيقات المستخدم. لذلك ربما لم يكن علينا إضافة الوسيطة deterministic إلى bmm. قد نفكر في كشف وظيفة داخلية إذا كنت تريد تبديل شيء ما مباشرةً ، ولكن لا ينبغي أن يكون deterministic متاحًا مباشرة على الوظيفة نفسها.

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

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

ال 67 كومينتر

هذا هو ممتاز مني. ستكون المشكلة في المقام الأول هي كيفية نشر هذا في كل مكان في قاعدة الشفرة ؛ ليس هناك ما هو أسوأ من الادعاء بأننا حتميين ، ولكن بعد ذلك في السر ليس الأمر كذلك :)

أنا جميعًا مع ذلك ، وسيكون أسلوبي هو الإبلاغ عن العمليات والخطأ عندما تكون الحتمية قيد التشغيل ونعلم أنها ليست كذلك.

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

أعتقد أنه يجب أن يكون الخيار الافتراضي هو الرمي ، لكن أعتقد أنه يمكننا دعم خاصية متعددة القيم هناك (غير الحتمية على ما يرام ، تحذير ، رمي).

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

خطأ ، تحذير ، وثائق مناسبة ...
هذا الأخير أمر لا بد منه.
تحذير أم خطأ؟ سأذهب مع وجود خطأ.

رمي يبدو رائعا. أتفق مع آدم في أن إعطاء خيار التحذير بدلاً من الرمي يبدو معقولاً.

شكرًا لوزنك. في النهاية ، الجهد الرئيسي للعلم الثلاثي هو العلم نفسه ، وهذا ليس بالأمر الصعب.
سأضيف علامة إلى Context.h ورش (عبر وظيفة مساعدة) AT_ERROR و AT_CHECK.

مرحبا،
أي أخبار هذا العلم؟
الحتمية أمر حاسم.
من واقع خبرتي ، يسمح الإصدار الحالي بالحتمية على وحدة معالجة رسومات واحدة ، بدقة تصل إلى 1e-16 ، باستخدام البذور الثابتة. لاحظ أنه قد يتم تضخيم الاختلاف المتناهي الصغر وتباعد النتائج.

من فضلك ، ضع في اعتبارك حالة multigpu أيضًا (على الأقل بالنسبة إلى K gpus ثابت ، يجب أن يكون السلوك حتميًا. أنا قادر على تحقيق نوع من الحتمية التي تتعطل من وقت لآخر لسبب لا أفهم الآن (باستخدام الإنشاء الليلي 1.2.0.dev20190616 ).). أنا أعاني من ذلك الآن ( 1 ، 2 ).

شكرا لك!

@ t-vi هل تعمل بنشاط على هذا؟

لا أريد منعك من فعل ذلك.

@ t-vi آسف إذا لم أكن واضحًا ، فأنا لا أخطط للعمل على هذا :). كنت أحاول فقط فهم ما إذا كان أي شخص يفعل ذلك بنشاط.

بعد ما يقرب من عام واحد ، لا تزال مشكلة الاستيفاء غير القطعي لم تحل بعد.

نأمل من المجتمع إضافة هذه الميزة :)

ربما يجلب الاستيفاء القطعي مساعدة كبيرة للمستخدمين.

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

سيكون الاستيفاء القطعي مساعدة كبيرة. حلقة الوصل

أولوية الارتداد ، esp لـ CUDA ، بناءً على ملاحظات المستخدم

أنا سعيد لأنه يتم إصلاحه ، شكرًا لك!

لكي نكون منصفين @ t-vi ، لا أعتقد أن "أولوية الارتداد" تعادل "يتم إصلاحه" :).

نتطلع إلى الحلول!

ذكر كولسبري أن أحد الأسباب القاتلة للخوارزميات الحتمية ليس لأن الحتمية هي المشكلة في الواقع ، ولكن يمكنك استبعادها عند تشغيل هذا ؛)

كيف يجب أن يتفاعل torch.experimental.deterministic مع بذرة RNG؟ هل يجب تعيين بذرة افتراضية إذا لم يتم تعيين البذور اليدوية؟ هل يجب أن يصدر تحذيرًا إذا لم يتم تعيين البذور اليدوية؟

أقترح عدم تعيين بذرة إذا لم يتم تعيين أي منها بواسطة المستخدم. لأحدها لأنه يجمع بين واجهتين غير مطلوبين (المستخدمون الذين يهتمون بالحتمية سيفهمون RNGs جيدًا على ما أعتقد). والأهم من ذلك ، من الصعب جدًا القيام بذلك بشكل موثوق ؛ يمكن للمرء استخدام RNG في تطبيقات متعددة العمليات / مترابطة ، ولديه فئات فرعية أخرى torch.Generator ، واستخدام numpy.random أيضًا ، إلخ.

لست متأكدًا من التحذير ، فقط إذا كان هناك مكان عاقل لتعيينه (على سبيل المثال ، هل ستجبر البذور قبل determinism=True بدلاً من نفس الوحدة / الوظيفة حيث يتم استخدام RNG؟).

أشعر بالفضول لأنه عندما أقوم بتعيين torch.backends.cudnn.deterministic=True ، فإن عامل الاستيفاء لا يزال غير حاسم. هل لا يستخدم الإقحام pytorch cudnn؟

ربما لا. يمكنك nvprof تشغيل إقحام الخاص بك للتحقق من بعض.

أتساءل عما إذا كان ينبغي لنا الاستمرار في تقديم الوسيطات deterministic في استدعاءات الوظائف بمجرد تنفيذ torch.experimental.deterministic لا. ربما يجب علينا ذلك ، لأن المستخدم قد يفضل الحتمية لبعض العمليات والسرعة لعمليات أخرى.

إذا احتفظنا بالوسيطات ، فماذا يحدث إذا كان torch.experimental.deterministic وعلامة deterministic للوظيفة يعارضان بعضهما البعض. هل يجب أن يعني torch.experimental.deterministic = True "استخدام الحتمية في جميع الحالات بغض النظر عن" ، أو يجب أن تعني "استخدام الحتمية كقيمة افتراضية ، ولكن إذا تم تحديد الوسيطة deterministic في استدعاء دالة ، فاستخدم هذا الإعداد لاستدعاء الوظيفة المحدد ". بمعنى آخر ، كيف ينبغي التعامل مع الكود أدناه؟ هل يعرف أحد كيف يعمل العلم torch.backends.cudnn.deterministic في موقف مشابه؟

torch.experimental.deterministic = True
torch.some_operation(deterministic=False)

@ kurtamohler سؤال جيد. أعتقد أن الحل الأسهل هو جعله bool? deterministic=None ، ثم تفسير None على أنه يعني "احترام torch.experimental.deterministic " ، وإلا استخدم بالضبط ما طلبه المستخدم.

لدينا نوعًا ما موقف مماثل مع الالتفاف ، ولكن الطريقة التي تم بها ذلك هناك كانت هناك convolution بدون وسيطة benchmark ، ثم _convolution مع صريح المعيار.

أعتقد أن أيًا من هذه الحلول سيكون مقبولًا ؛ ومع ذلك ، فإن أسلوب الالتفاف له فائدة إضافية تتمثل في عدم تسريب العلامة deterministic إلى واجهة برمجة التطبيقات المرئية للمستخدم (ما لم يستخدموا واجهة برمجة تطبيقات داخلية).

ما هو الأساس المنطقي لـ "أريد أن أكون حتمية في كل مكان ، لكن _ليس في هذا العامل المحدد _"؟ هل من المفترض حقًا أن تكون هذه حالة استخدام شائعة بدرجة كافية لضمان إضافة مدخلات إضافية للعديد من مشغلينا (ومعظم المشغلين المعقدين)؟ سيكون من الأفضل IMO توفير مديري السياق لتبديل الحتمية.

apaszke ، نعم أعتقد أنك محق في أنه سيكون من الأفضل فقط استخدام مديري السياق لتبديل الحتمية. لن أقول إننا يجب أن نضيف الوسيطة deterministic إلى أي عوامل تشغيل ، لكن بعض المشغلين يمتلكونها بالفعل. هل سيكون من الأفضل إزالة كل هؤلاء وكسر BC ، أم أنه من الأفضل الاحتفاظ بهم والسماح لهم بتجاوز torch.experimental.deterministic ؟

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

أنا أتساءل عما إذا كانت السمة الحتمية لوظيفة الاستيفاء مغلقة ولن يتم تنفيذها؟

كلا ، نحن قادرون على الإصدارات القطعية لجميع الوظائف في PyTorch

ezyang أي إصدار pytorch له وظيفة F.interpolate الحتمية؟ هل يبدأ من pytorch 1.6؟ أم أنه متوفر في أحدث إصدار مستقر (1.5)؟ أو هل يجب علي تنزيل وتثبيت Pytorch من المصدر؟

سأكون سعيدًا لبدء العمل على هذا

يضيف الالتزام أعلاه العلامة فقط ، ولا يؤثر على أي عمليات حتى الآن. سأكون ممتنًا لو استطاع شخص ما قضاء بضع دقائق للنظر في الأمر وإخباري إذا فعلت أي شيء بشكل غير صحيح أو إذا كان من الممكن تحسين أي شيء حتى الآن. لقد استندت في هذا إلى كيفية تنفيذ torch.backends.cudnn.deterministic .

يبدو هذا جيدًا ولكني أشعر أن التسمية الداخلية لا ينبغي أن تتضمن التجربة (نظرًا لأنك ، ظاهريًا ، يومًا ما تريد جعلها غير تجريبية ، ولا ينبغي أن يتضمن ذلك الاضطرار إلى إعادة تسمية جميع بتات التنفيذ!)

ezyang ، نعم هذا منطقي ،

لقد أضفت torch.experimental.deterministic_error_level ، على غرار ما فعله @ t-vi في عمله السابق حول هذه المسألة. يتحكم deterministic_error_level في سلوك الخطأ / التحذير إذا لم يكن لدى deterministic == True ووظيفة معينة تنفيذ حتمي. يمكن ضبطه على 2 (خطأ) أو 1 (تحذير) أو 0 (صامت).

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

هذا ما يحدث عندما يفشل هذا الفحص:

>>> import torch
>>> try:
...     torch.experimental.deterministic_error_level=50
... except:
...     print('exception caught')
... 
terminate called after throwing an instance of 'c10::Error'
  what():  error level 50 is invalid, must be one of 0: None, 1: Warn, or 2: Error
Exception raised from longToErrorLevel at ../aten/src/ATen/Context.cpp:85 (most recent call first):
frame #0: c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) + 0x58 (0x7f53e2cc0878 in /work/kurtamohler/development/pytorch-deterministic-flag/torch/lib/libc10.so)
frame #1: at::Context::longToErrorLevel(long) + 0x122 (0x7f53f6d61a82 in /work/kurtamohler/development/pytorch-deterministic-flag/torch/lib/libtorch_cpu.so)
frame #2: THPModule_setDeterministicErrorLevel(_object*, _object*) + 0x31 (0x7f53fb5625d1 in /work/kurtamohler/development/pytorch-deterministic-flag/torch/lib/libtorch_python.so)
<omitting python frames>
frame #23: __libc_start_main + 0xe7 (0x7f5432d62b97 in /lib/x86_64-linux-gnu/libc.so.6)

Aborted (core dumped)

إذا كان أي شخص يعرف كيف يمكنني إصلاح ذلك ، فيرجى إبلاغي بذلك.

kurtamohler هل THPModule_setDeterministicErrorLevel مفقود HANDLE_TH_ERRORS / END_ HANDLE_TH_ERRORS وحدات ماكرو؟ هناك حاجة لالتقاط استثناء C ++ وترجمته إلى إرجاع خطأ Python.

آه هذا كل شيء ، شكرًاcolesbury!

لقد بدأت في إضافة التنبيه غير القطعي لجميع المتصلين بـ atomicAdd . لقد لاحظت أن بعض المتصلين يستخدمون atomicAdd في حالات معينة. على سبيل المثال ، يستخدم adaptive_avg_pool3d_backward فقط إذا كان (isizeW%osizeW != 0) || (isizeH%osizeH != 0) || (isizeT%osizeT != 0) صحيحًا. هل يجب علي التنبيه في هذه الحالات فقط ومحاولة نقلها في رسالة الخطأ ، أم أنه من الجيد التنبيه عندما يتم استدعاء هذه الوظائف سواء تم استخدام atomicAdd أم لا؟

ربما يكون التنفيذ أسهل وأسهل للفهم إذا كنت تنبه دون قيد أو شرط.

ngimel ، لقد كنت أفكر في كيفية استخدام CUBLAS_WORKSPACE_CONFIG لضمان استخدام دفق محدد ، وأعتقد أن هناك طريقتين رئيسيتين يجب أخذهما في الاعتبار.

إذا كان شخص ما يستخدم أحد إصدارات CUDA المتأثرة (10.2 أو أعلى في الوقت الحالي) ، وتم استدعاء torch.set_deterministic(True) ، فاستخدم std::getenv للتأكد من أن CUBLAS_WORKSPACE_CONFIG هو إما :16:8 أو :4096:8 . إذا لم يكن كذلك ، فقم بإجراء إما (1) أو (2):

  1. ألقى خطأ بإخبار المستخدم بتعيين المتغير بشكل مناسب.

  2. اضبط المتغير تلقائيًا على putenv ( _putenv على Windows). ومع ذلك ، هناك بعض قرارات التصميم الأخرى المرتبطة بهذا. هل يجب أن نختار :16:8 (أداء أقل ، لكن استخدام ذاكرة أقل) أو :4096:8 (أداء أعلى ، لكن استخدام ذاكرة أكبر)؟ أيضًا ، إذا قام المستخدم بتعيين المتغير على قيمة غير حتمية أخرى ، فسنضطر إما إلى تتبع القيمة الأصلية واستعادتها إذا تم استدعاء torch.set_deterministic(False) ، أو يمكن أن نخطئ لإخبار المستخدم بذلك يحتاجون إلى إلغاء ضبط المتغير أو مخطط آخر.

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

هل لديك رأي قوي حول الخيار الأفضل؟ من المحتمل أن يكون الخيار (2) أكثر سهولة في الاستخدام ، ولكنه قد يكون أقل شفافية من الخيار (1).

لا أعرف ما إذا كان تعيين المتغير أثناء تشغيل التطبيق بالفعل سيكون له أي تأثير

لمتابعة هذا السؤال ، لا يبدو أن تعيين متغير البيئة داخل برنامج نصي pytorch يؤثر على حتمية تيار CUDA. لقد قمت بتعديل البرنامج النصي من https://github.com/pytorch/pytorch/issues/39849 للتشغيل عدة مرات ومقارنة إحصائيات التدريب للتحقق من السلوك غير الحتمي. يحاول تعيين CUBLAS_WORKSPACE_CONFIG=:4096:8 لضمان استخدام الدفق الحتمي: https://github.com/kurtamohler/pytorch-perf-test-scripts/blob/master/nondeterministic_alert/cuda_stream_nondeterminism.py

يوضح تشغيله أننا لا نحصل على سلوك حتمي من تعيين المتغير داخل البرنامج النصي:

$ python cuda_stream_nondeterminism.py 
Before setting var: not deterministic
After setting var: not deterministic
After restoring old var: not deterministic

لكن تشغيله مع مجموعة متغير البيئة خارج البرنامج النصي يجعله حتميًا:

$ CUBLAS_WORKSPACE_CONFIG=:4096:8 python cuda_stream_nondeterminism.py 
Before setting var: possibly deterministic
After setting var: possibly deterministic
After restoring old var: possibly deterministic

لاحظ أنه يطبع "ربما حتمية" لأنني أقوم بتشغيل وظيفة التدريب 5 مرات فقط ، ومن الممكن أن تصبح محظوظًا حتى لو لم يكن السلوك حتميًا حقًا.

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

اكتشفت أنه يمكنني إنشاء دفق جديد واستخدامه باستخدام:

with  torch.cuda.stream(torch.cuda.Stream()):

لكن الدفق الجديد لا يحترم إعداد متغير البيئة المتغير. لقد وجدت أيضًا torch.cuda.init() ، لكن لسوء الحظ ، هذا أمر غير متاح إذا تم بالفعل تهيئة cuda.

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

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

حاليًا ، لا يبدو أنه من الممكن التحقق من إصدار CUDA من ملف مترجم غير nvcc ، لذلك أعتقد أنه سيتعين علي إضافة ذلك إلى aten/src/ATen/cuda/detail/CUDAHooks.h (التحقق من إصدار cuDNN جزء من تلك الواجهة) . إذا كان أي شخص يعرف أي شيء أفضل ، يرجى إعلامي.

الالتزام أعلاه يضيف الخطأ. لكني بحاجة إلى معرفة ما يجب فعله باختبارات الوحدة الآن. هناك مشكلتان:

  • من أجل اختبار أن الخطأ يتم طرحه في الحالة الصحيحة (لم يتم تعيين cuda> = 10.2 و CUBLAS_WORKSPACE_CONFIG بشكل صحيح) ، يجب أن تكون البنية التحتية للاختبار قادرة على تغيير متغير البيئة تلقائيًا قبل تشغيل الاختبار
  • للتأكد من عدم كسر اختبارات torch.set_deterministic ، سنحتاج إلى تعيين CUBLAS_WORKSPACE_CONFIG تلقائيًا بشكل صحيح. يمكننا تعيين هذا المتغير افتراضيًا في جميع وظائف CI التي تستخدم cuda> = 10.2.

اكتشفت أنني قادر على تعيين متغيرات البيئة من برنامج نصي بيثون ، ثم أعد تحميل وحدة الشعلة لجعلها تحترم القيمة الجديدة:

>>> import torch
>>> torch.set_deterministic(True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/work/kurtamohler/development/pytorch-deterministic-flag-cuda-env-var/torch/__init__.py", line 306, in set_deterministic
    _C._set_deterministic(d)
RuntimeError: To enable deterministic behavior with CUDA >= 10.2, you must set environment variable CUBLAS_WORKSPACE_CONFIG=:4096:8 or CUBLAS_WORKSPACE_CONFIG=:16:8. For more information, go to https://docs.nvidia.com/cuda/cublas/index.html#cublasApi_reproducibility
>>> import os
>>> os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8'
>>> from importlib import reload
>>> torch = reload(torch)
>>> torch.set_deterministic(True)

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

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

الالتزام أعلاه يعالج جميع المخاوف التي ذكرتها في تعليقي السابق. لقد أضفت مصممًا لإغلاق أي اختبار لواجهة برمجة التطبيقات يستدعي torch.set_deterministic() ، وقمت بتعيين CUBLAS_WORKSPACE_CONFIG=:4096:8 مؤقتًا فقط إذا لزم الأمر. كما أنه يعيد العلامة الحتمية وإعدادات CUBLAS_WORKSPACE_CONFIG إلى ما كانت عليه قبل تشغيل الاختبار.

لقد أدركت أن مستند التكاثر يذكر أن سلوك CuDNN الحتمي يتطلب:

torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

هل يعرف شخص ما في هذا الموضوع ما هو benchmark بالضبط ، ولماذا torch.backends.cudnn.deterministic = True وحده لا يكفي؟

قد نرغب في فرض إيقاف تشغيل benchmark إذا كان torch.is_deterministic() == True . بمعنى آخر ، بدلاً من تمرير ctx.benchmarkCuDNN() مباشرة إلى at::_convolution() ، ربما يجب أن يكون ctx.benchmarkCuDNN() && !ctx.deterministic() على هذا السطر: https://github.com/pytorch/pytorch/blob/ ماجستير / aten / src / ATen / native / Convolution.cpp # L602

إذا لم نجري هذا التغيير ، فيبدو أن الأشخاص الذين يستخدمون set_deterministic وسيتعين على CuDNN القيام بذلك:

torch.set_deterministic(True)
torch.backends.cudnn.benchmark = False

بمعنى أن set_deterministic() وحده لن يغطي كل شيء ، وهو أمر محير في رأيي.

سم مكعبezyangcolesbury @ تي السادسngimel

عند مواجهة تكوين التفاف جديد ، يقوم benchmark=True بتشغيل جميع تطبيقات cudnn المتاحة واختيار أسرعها ، وتخزين التنفيذ الذي اختاره مؤقتًا ، لذلك ستستخدمه جميع الاستدعاءات اللاحقة للالتفاف باستخدام نفس المعلمات. لذلك ، إذا تم تعيين deterministic أيضًا على True ، فستكون النتائج حتمية طالما استمرت ذاكرة التخزين المؤقت هذه ، أي طالما أنك في نفس العملية. إذا كانت هناك عمليات تنفيذ ذات وقت تشغيل قريب ، في المرة التالية التي تبدأ فيها العملية وتقوم بإجراء قياس الأداء مرة أخرى ، فقد يفوز تطبيق آخر ، وستكون النتائج (رغم أنها لا تزال حتمية بالمعنى الموضح أعلاه) مختلفة عن التشغيل السابق. لذلك ، لضمان الحتمية بين الدورات ، عليك إيقاف قياس الأداء.

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

لقد أنشأت صفحة wiki لمساعدة مساهمي PyTorch على إضافة دعم لـ torch.set_deterministic() : https://github.com/pytorch/pytorch/wiki/How-to-support-٪60torch.set_deterministic ()٪ 60-in- مشغلي PyTorch

نرحب بأي تحسينات.

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

مرحبًا ، أريد التحدث عن خطة المضي قدمًا مقابل torch.deterministic . هناك بعض الأسئلة عالية المستوى التي نحتاج إلى الإجابة عليها:

  1. ما هي دلالات torch.deterministic ؟ ماذا يتوقع المستخدم؟ هل أفضل جهد مفيد بالفعل للمستخدم؟ إذا لم يكن مفيدا، أنه من الأفضل أن تحدد torch.deterministic من حيث ما العمليات التي تسيطر عليها؟
  2. الآن بعد أن أصبح لدينا علامة torch.deterministic ، فهل من المنطقي إزالة وسيطة الكلمة الرئيسية deterministic= بالكامل من واجهة API العامة ( bmm ، أنا أنظر إليك).
  3. ما هي نهاية اللعبة لهذا العمل؟ ما مقدار ما ستعمل عليه (kurtamohler) ، مقابل المجتمع العام ، وعندما نصل إلى نهاية مهمتك هنا ، كيف تبدو الحالة المعقولة؟

بدءًا من (1) ، تقول التوثيق الحالي لـ torch.deterministic:

     r"""Sets a global flag to force all operations to use a deterministic
    implementation if available. If an operation that does not have a
    deterministic implementation is called while this setting is True, the
    operation will throw a RuntimeError.

    Note that deterministic operations tend to have worse performance than
    non-deterministic operations.

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

يمكننا تغيير توثيق torch.deterministic لتحسين هذا. بعض التغييرات الممكنة:

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

النقطة الثانية تؤدي إلى (2): إذا وجدت torch.deterministic الآن كطريقة لتبديل الحتمية ، فمن الأقل أهمية دعم الحتمية مباشرة في واجهة برمجة تطبيقات المستخدم. لذلك ربما لم يكن علينا إضافة الوسيطة deterministic إلى bmm. قد نفكر في كشف وظيفة داخلية إذا كنت تريد تبديل شيء ما مباشرةً ، ولكن لا ينبغي أن يكون deterministic متاحًا مباشرة على الوظيفة نفسها.

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

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

@ zou3519 تتقاطع مع Q أيضًا على https://github.com/pytorch/pytorch/pull/38683#issuecomment -662590937

أنا سعيد لأنك طرحت هذه الأسئلة على ezyang و @ zou3519 وmruberry. أوافق على أن الوثائق التي كتبتها هي تمثيل خاطئ للوضع الحالي.

تعجبني فكرة سرد جميع الوظائف التي تؤثر على torch.set_deterministic() شامل ، حتى لا نكذب على المستخدم. شكرًا لإضافة ذلك إلى 1.6.0 ، @ zou3519.

أوافق على أنه لا ينبغي أن نقدم الإعداد deterministic كوسيطات دالة مباشرة.

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

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

  1. حتمية
  2. غير حتمية بشكل افتراضي ، ولكن لديها دعم للعلامة الحتمية (إما خطأ أو تنفيذ بديل)
  3. غير حتمي ولا يدعم العلامة الحتمية

بالطبع الحالة المثالية هي حذف الفئة 3 تمامًا ، ومن ثم ستكون قائمة وظائف الفئة 2 كافية. ومع ذلك ، ستظل وظائف الفئة 3 موجودة لفترة زمنية طويلة (أو ربما إلى الأبد ، إذا لم يكن جميع المساهمين على دراية بمسألة الحتمية ، أو يؤدي الالتزام إلى إزالة الحتمية عن طريق الخطأ لوظيفة ما ، وما إلى ذلك). لذلك حتى إذا كانت لدينا قائمة شاملة لجميع وظائف الفئة 2 ، فليس لدى المستخدم طريقة بسيطة لمعرفة ما إذا كانت الوظيفة التي لا تظهر في القائمة حتمية أم لا (يمكن أن تكون الفئة 1 أو 3). على سبيل المثال ، torch.add لا يظهر في القائمة ، فكيف يعرف المستخدم أنها حتمية؟

ربما يمكننا التفكير في الاحتفاظ بقائمة وظائف الفئة 3 أيضًا. لكن الاحتفاظ بهذه القوائم يدويًا سيكون أمرًا صعبًا للغاية لأسباب عديدة ، لذلك أتساءل عما إذا كان بإمكاننا جعلها آلية إلى حد ما. من المحتمل أن نضع وظيفة CI التي تجري اختبارات الحتمية على جميع الوظائف. ليس من الممكن أن تثبت حثيًا بنسبة 100٪ أن الوظيفة حتمية ، وأن الوظيفة غير الحتمية قد تعطي أحيانًا نفس النتيجة عدة مرات إذا لم يحالفنا الحظ. ولكن كلما أجرينا هذه الاختبارات في كثير من الأحيان ، زادت ثقتنا بشأن الفئة التي تشكل كل وظيفة جزءًا منها.

هناك أيضًا سؤال حول كيفية نقل كل ما نعرفه ولا نعرفه عن كل وظيفة وكل نظام أساسي إلى المستخدم بكفاءة. ربما يمكننا عمل جدول لجميع وظائف الفئة 2 و 3 على كل منصة. سيكون من الجيد أن تتحقق اختبارات الحتمية تلقائيًا من صحة هذا الجدول.

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

هل torch.add حتمية؟

import torch
n = 512
device = 'cuda'
a = torch.arange(n**3, device=device, dtype=torch.float32)
a = a.reshape((n, n, n))
b = torch.arange(n**3, device=device, dtype=torch.float32)
b = b.reshape((n, n, n))
out_zero = torch.zeros((n, n, n), device=device)
out_zero = out_zero.set_(out_zero.storage(), storage_offset=0, size=a.size(), stride=(1,1,1))
out_one = torch.zeros((n, n, n), device=device)
out_one = out_one.set_(out_one.storage(), storage_offset=0, size=a.size(), stride=(1,1,1))

torch.add(a, b, out=out_zero)
torch.add(a, b, out=out_one)
(out_zero == out_one).all()
: tensor(False, device='cuda:0')

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

يبدو إدراج العمليات المتأثرة بعلامة "الحتمية" جيدًا. بالتراجع قليلاً ، يبدو أننا نتحدث حقًا عن شيئين:

  • طلب إصدارات محددة للعمليات ، إذا كانت متوفرة ( use_deterministic ؟)
  • تحذير إذا كانت العملية غير حتمية

يبدو أن علم أول شيء واضح ومباشر. والثاني ، مع ذلك ، أكثر تعقيدًا بعض الشيء. أخشى أنه من الصعب معرفة ما إذا كانت عمليات مكتبات الرياضيات مثل oneDNN و cuDNN و MAGMA حتمية ، خاصة عبر الإصدارات والأجهزة. هل لديك فكرة عن أفضل السبل للتعامل مع هذا ، @ kurtamohler؟ ربما يمكننا التحذير من جميع العمليات غير الحتمية المحلية وأيضًا التحذير عند إجراء مكالمات مكتبة الرياضيات أيضًا؟ لا ينبغي أن يكون التحذير مرة واحدة في كل عملية تدخليًا.

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

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

أعتقد أننا لا ينبغي أن ندع الكمال يكون عدو الخير هنا. لا أعرف متى كان استخدام موترات متداخلة مع PyTorch آمنًا بنسبة 100٪ ، وانطباعي هو أنه لا يستخدمها عامة الناس.

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

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

لا أعرف متى كان استخدام موترات متداخلة مع PyTorch آمنًا بنسبة 100٪ ، وانطباعي هو أنه لا يستخدمها عامة الناس.

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

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

قد يقول الطبيب شيئًا مثل ، "مكالمات مكتبة الرياضيات التي من المعروف أنها غير حتمية ..."؟

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

نظرًا لأن الكثير من الأفكار كانت تطفو ، اسمح لي فقط بالتناغم مع أفكاري المحددة حول بعضها:

  1. "ربما يمكننا التفكير في الاحتفاظ بقائمة وظائف الفئة 3 أيضًا." يبدو أن هذا يتطلب الكثير من العمل. أعتقد أنه من المحتمل أن يكون الأمر يستحق ذلك فقط للوظائف حيث قمنا صراحة بعمل بعض التسهيلات للحتمية (على الأرجح ، الوظائف التي تدعم العلم الحتمية)
  2. "من المحتمل أن نؤسس وظيفة CI التي تجري اختبارات الحتمية على جميع الوظائف." أعتقد أنه يجب القيام بشيء من هذا القبيل بعناية كبيرة ، لأنه بحكم طبيعته يختبر شيئًا غير حتمي ، وهذا يعني أن اختبار الحتمية نفسه "غير مستقر" (سوف يمر أحيانًا ويفشل الآخرين) . لا تتعامل أدوات الإبلاغ عن CI الخاصة بنا مع مثل هذه المواقف بشكل جيد للغاية.
  3. "الثاني ، مع ذلك ، أصعب قليلاً. أخشى أنه من الصعب معرفة ما إذا كانت عمليات مكتبات الرياضيات مثل oneDNN و cuDNN و MAGMA حتمية ، خاصة عبر الإصدارات والأجهزة." يجب أن نبذل قصارى جهدنا هذا. في كثير من الحالات ، تحدد مكتبة الرياضيات صراحةً في وثائقها أنها حتمية أم لا ، وعلينا ببساطة الإبلاغ بأمانة عما يقوله المستندات
  4. "ربما يمكننا التحذير من جميع العمليات غير الحتمية المحلية وأيضًا التحذير عند إجراء استدعاءات مكتبة الرياضيات أيضًا؟" لا أعتقد أننا يجب أن نفعل هذا. عندما نحذر من اللاحتمية ، يجب أن يكون ذلك بسبب حدوث اللاحتمية ، وليس لأنه قد يحدث. إذا أفرطت في التحذير ، فسيبدأ الناس في تجاهل التحذيرات.

لا أعتقد أننا يجب أن نقلق بشأن حتمية الإصدار / الأجهزة - حظًا سعيدًا في ذلك.

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

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

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

بالتأكيد ، ولكن لا يمكن للمستخدم أيضًا إشراكنا في خدعهم غير الحتمية ، ومن ثم بالطبع لن تتوقع أن يتم تحذيرك بعد ذلك ؛)

أعتقد أنه يمكننا إغلاق هذه المشكلة الآن نظرًا لوجود واجهة برمجة تطبيقات العلم وموثقة جيدًا.

تضمين التغريدة شكرا لك.

هل يعني ذلك أنه يمكننا استخدام torch.manual_seed(111) لتعيين كل شيء حتميًا ، بما في ذلك العملية interpolation ؟

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

يبدو الاستيفاء على وجه الخصوص شيئًا يمكن جعله حتميًا من خلال كتابة ليس كل ذلك النواة المعقدة للخلف.

@ t-vi مرحبًا ، الآن بعد أن تم إصدار pytorch 1.7 ، هل تم تحديث الاستيفاء للخلف kernel؟

لذا فإن حبات اختزال CUDA والعكس بالعكس تقع في aten/src/ATen/native/cuda/UpSample* . يقترح grep أن الخطي ، الخطي ، المكعب له اتجاه عكسي غير محدد (لديهم علامة تحذير) ، لكن الأقرب لا يفعل ذلك.
@ kurtamohler سيكون الشخص الأفضل بكثير

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