سؤال

في تجربتي، هو 2 إلى 3 مرات أبطأ من الرمز الأصلي. (قمت بتنفيذ L-BFGS لتحسين متعدد المتغيرات).

لقد تتبعت الإعلانات على Stackoverflow إلىhttp://www.centerspace.net/products/

السرعة مذهلة حقا، السرعة قريبة من الرمز الأصلي. كيف يفعلون ذلك؟ هم قالوا ذلك:

س: هل Nmath "نقي".

تعتمد الجواب إلى حد ما على تعريفك "نقي .NET". مكتوب NMATH في C #، بالإضافة إلى طبقة C ++ صغيرة تدار. لأداء أفضل لعمليات الجبر الخطية الأساسية، ومع ذلك، فإن NMATH يعتمد على مكتبة نواة الرياضيات المحلية الأصلية (المضمنة مع NMATH). ولكن لا توجد مكونات COM، لا DLLs - مجرد جمعيات .NET. أيضا، يتم تخصيص جميع الذاكرة المخصصة في طبقة C ++ المدارة واستخدامها بواسطة الكود الأصلي من الكومة المدارة.

يمكن للشخص أن يفسر أكثر لي؟

هل كانت مفيدة؟

المحلول

النقطة حول C ++ / CLI صحيحة. لإكمال الصورة، فقط نقطتين إضافيتين مثيرة للاهتمام:

  • .NET إدارة الذاكرة (جامع القمامة) من الواضح أنها ليست هي المشكلة هنا، كما لا يزال Nmath يعتمد على ذلك

  • يتم توفير ميزة الأداء بالفعل من قبل Intel MKL، والتي توفر تطبيقات محسنة للغاية بالنسبة للعديد من وحدات المعالجة المركزية. من وجهة نظري، هذه هي النقطة الأساسية. باستخدام رمز مستقيم إلى الأمام، لن يمنحك رمز NAIV C / C ++ بالضرورة أداء فائقا أكثر من C # /. Net، في بعض الأحيان أسوأ. ومع ذلك، يسمح لك C ++ / CLI باستغلال جميع خيارات التحسين "القذر".

نصائح أخرى

كيف يفعلون ذلك؟

مثل معظم المكتبات العددية ل .NET، NMATH أكثر قليلا من التفاف فوق Intel MKL المضمن في تجميع .NET، ربما عن طريق ربط مع C ++ / CLI لإنشاء التجمع المختلط. وبعد ربما ربما مرجعت تلك البتات التي لا تكون مكتوبة بالفعل في .NET.

مقالات مجلة F # .NET المكتبات العددية: وظائف خاصة، واستيفاء وأرقام عشوائية (16 مارس 2008) و المكتبات العددية: الجبر الخطي والأساليب الطيفية (16 أبريل 2008) اختبار القليل من الوظائف و Nmath كان في الواقع أبطأ جميع المكتبات التجارية. PRNG كانت أبطأ من الآخرين و 50٪ أبطأ من مكتبة الرياضيات المجانية، كانت بعض الوظائف الأساسية مفقودة (مثل القدرة على حساب Gamma(-0.5)) والوظائف الأساسية الأخرى (وظائف Gamma التي تقدمها) تم كسرها. فاز كل من التحسين المتطرف و BlueBit على Nmath في معيار Eigensolver. Nmath لم تقدم حتى تحويل فورييه في ذلك الوقت.

والأكثر من المستغمة، كانت تباينات الأداء ضخمة في بعض الأحيان. وكانت المكتبة العددية التجارية الأكثر تكلفة التي اختبرناها (IMSL) أكثر من 500 × أبطأ من مكتبة FFTW المجانية في معيار FFT و لا أحد من المكتبات قدمت أي استخدام للنوى المتعددة في ذلك الوقت.

في الواقع، كانت هذه بالضبط نوعية رديئة لهذه المكتبات التي شجعتنا على تسويقنا F # للرقم المكتبة (التي هي رمز F # النقي 100٪).

أنا واحد من المطورين الرصاص ilnumerics.. وبعد لذلك أنا متحيز، من الواضح؛) لكننا نكشف عنها أكثر فيما يتعلق بالجنديين، لذلك سأقدم بعض الأفكار لنا سرعة "أسرار".

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

  1. إدارة ذاكرتك بشكل مناسب! ستؤدي إدارة الذاكرة السذاجة إلى أداء سيء، لأنه يشدد على GC بشكل سيء، يسبب تجزئة الذاكرة ويحلل من محلية الذاكرة (وبالتالي أداء ذاكرة التخزين المؤقت). في بيئة مجمعة مع القمامة مثل .NET، هذا يتلخص للمنع من تخصيصات الذاكرة المتكررة. في ilnumerics، قمنا بتنفيذ تجمع ذاكرة عالية الأداء من أجل Archieve هذا الهدف (والتخلص من الصفائف المؤقتة الحديثة للحصول على بناء جملة نيس ومريح دون دلالات دالة سلاخ).

  2. الاستفادة من التوازي! هذه الأهداف على حد سواء: موازية مستوى الموضوع والتوازي على مستوى البيانات. يتم استخدام النوى المتعددة بواسطة أجزاء المحطات المكثفة من الحسابات. على X86 / X64 CPUS ملحقات SIMD / الوسائط المتعددة مثل SSE.XX و AVX السماح بسعر صغير ولكنه فعال. انهم لا يتعلمون مباشرة من قبل لغات .Net الحالية. وهذا هو السبب الوحيد، لماذا لا يزال MKL أسرع من رمز .NET "نقي". (ولكن الحلول ترتفع بالفعل.)

  3. لرفع سرعة اللغات المحسنة للغاية مثل Fortran و C ++، يجب أن يتم تطبيق نفس الأمثل على التعليمات البرمجية الخاصة بك كما فعلت لهم. C # تقدم الخيار يفعل ذلك.

ملاحظة، يجب اتباع هذه الاحتياطات في هذا الترتيب! لا معنى له العناية بملحقات SSE أو حتى إزالة الاختيار المرتبط، إذا كانت BoTleneck هي Bandwith الذاكرة والمعالج (S) تقضي معظم الوقت في انتظار بيانات جديدة. أيضا، بالنسبة للعديد من العمليات البسيطة التي لا تدفع حتى لاستثمار الجهود الضخمة لرفع مقياس صغير آخر حتى أداء الذروة! النظر في المثال المشترك لدالة Lapack Daxpy. يضيف عناصر المتجه X إلى العنصر المقابل من نوع ناقلات آخر Y. إذا تم ذلك لأول مرة، فسيتعين على جميع الذاكرة الخاصة ب X و Y أن يتم إحضارها من الذاكرة الرئيسية. هناك القليل لا شيء يمكنك القيام به حيال ذلك. والذاكرة هي عنق الزجاجة! لذلك بغض النظر عما إذا كانت الإضافة في النهاية تتم الطريقة الساذجة في C #

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}

أو القيام به باستخدام استراتيجيات Vectorization - سيكون يجب أن تنتظر الذاكرة!

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

إذا كنت مهتما، فيمكنك الكشف عن تنفيذ L-BFGS؟ سأكون سعيدا بتحويلها إلى ilnumerics ونتائج مقارنة بعد ذلك وأنا متأكد من أن المكتبات الأخرى المدرجة هنا ترغب في اتباعها. (؟)

لقد نشرت مدونة شرط معالجة هذا السؤال.

المفتاح هو C ++ / CLI. وبعد يسمح لك بتجميع كود C ++ في تجميع .NET المدارة.

اليوم قياسي الصناعة لجعل مختلط .NET / المكتبات الأصلية من أجل اتخاذ مزايا كلا النظامين لتحسين الأداء. ليس فقط Nmath، العديد من المكتبات التجارية والمجانية مع واجهة .NET تعمل مثل هذا. على سبيل المثال: عدسيات math.net، dnanalytics., ، التحسين الشديد، finmath. وغيرها الكثير. إن التكامل مع MKL هو شعبية للغاية بالنسبة لمكتبات .NET العددية، ومعظمها فقط استخدم التجميع المدير C ++ كمستوى متوسط. ولكن هذا الحل لديه عدد من العيوب:

  1. Intel MKL هو برنامج ملكي وهو مكلف بعض الشيء. لكن بعض المكتبات مثل Dnanalytics توفر استبدال مجاني بوظائف MKL مع رمز .NET النقي. بالطبع، إنها أبطأ بكثير، لكنها مجانية وظيفية كاملة.

  2. إنه يقلل من توافقك الذي تحتاجه للحصول على DLL DLL من Kernel C ++ المدارة الثقيلة لكل من وضع 32 بت و 64 بت.

  3. تمكنت من الدعوات الأصلية تحتاج إلى أداء التنظيم التي تبطئ أداء عمليات سريعة تسمى بشكل متكرر مثل Gamma أو NormalCDF.

آخر مشاكل حلها في مكتبة rtmath finmath. أنا لا أعرف حقا كيف فعلوا ذلك، لكنها توفر DLL نقية واحدة نقية والتي تم تجميعها لأي منصة وحدة المعالجة المركزية وتدعم 32 بت و 64 بت. كما أنني لم أر أي تدهور أداء ضد MKL عندما أحتاج إلى استدعاء TimalCDF Billions Times.

نظرا لأن Intel MQL (الأصلي) تقوم بعمل الرياضيات، فأنت في الواقع لا تفعل الرياضيات في التعليمات البرمجية المدارة. أنت مجرد استخدام مدير الذاكرة من .NET، لذلك يتم استخدام النتائج بسهولة بواسطة .NET Code.

لقد تعلمت المزيد من النموذج تعليق Darin Dimitrov على إجابته و Levor Misfeldt تعليق على تعليق @ دارين. وبالتالي نشرها كإجابة، للقراء في المستقبل.

يستخدم Nmath P / Invoke أو C ++ CLI للاتصال بمكتبة Intel Math Kernel الوظائف المحلية التي يتم فيها إجراء الحسابات الأكثر كثافة والتي هي السبب في أنها سريعة جدا.

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

أيضا @ بلوق بولس هو أيضا قراءة جيدة. إليك الملخص.

C # سريع، تخصيص الذاكرة ليست كذلك. إعادة استخدام المتغيرات كما المعلمات Ref أو خارج, ، بدلا من إرجاع المتغيرات الجديدة من الأساليب. تخصيص متغير جديد يستهلك الذاكرة ويبطئ التنفيذ. @ Haymo Kutschbach شرح هذا جيدا.

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

بالنسبة للعديد من الحسابات القصيرة، لاستدعاء روتين C ++ / CLI من C #، تعلق جميع المؤشرات على البيانات المخصصة في المساحة المدارة، ثم استدعاء مكتبة Intel أفضل بشكل عام من استخدام P / Invoke للاتصال بالمكتبة مباشرة من C #، بسبب تكلفة تنظيم البيانات. كما ذكرنا haymo kutschbach في التعليقات، لأنواع اضادقة ولكن لا يوجد فرق بين C ++ / CLI و C #. يتم تثبيت صفائف أنواع ودروس أقراص تحتوي على أعضاء قابلة لإضاءة فقط بدلا من نسخها أثناء التنظيم. أشير https://msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.110).aspx. للحصول على قائمة الأنواع القابلة لإضاءة وغير قابل للتطبيق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top