سؤال

أود أن نسخة قصيرة نسبيا تسلسل الذاكرة (أقل من 1 كيلو بايت, عادة 2-200 بايت) في وقت حرج وظيفة.أفضل كود على وحدة المعالجة المركزية الجانب يبدو أن rep movsd.ومع ذلك أنا لا يمكن أن تجعل بلدي مترجم لتوليد هذا القانون.تمنيت (وأنا أتذكر رؤية ذلك) باستخدام memcpy أن تفعل هذا باستخدام مترجم المدمج في إينترينسيكس ، ولكن على أساس التفكيك و التصحيح يبدو أن المترجم هو استخدام الدعوة إلى memcpy/memmove مكتبة التنفيذ بدلا من ذلك.كما يأمل المترجم قد تكون ذكية بما فيه الكفاية للاعتراف التالية حلقة واستخدام rep movsd من تلقاء نفسها, ولكن يبدو أنه لا يفعل ذلك.

char *dst;
const char *src;
// ...
for (int r=size; --r>=0; ) *dst++ = *src++;

هل هناك طريقة لجعل Visual Studio مترجم لتوليد rep movsd سلسلة أخرى من استخدام مضمنة الجمعية ؟

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

المحلول 3

باستخدام memcpy مع حجم ثابت

ما وجدته في الوقت نفسه:

سوف يستخدم برنامج التحويل البرمجي جوهريا عندما يكون حجم الكتلة المنسوخة هو تجميع الوقت المعروف. عندما لا يكون، يدعو في تنفيذ المكتبة. عندما يكون الحجم معروفا، فإن التعليمات البرمجية التي تم إنشاؤها لطيفة جدا ومحددة بناء على الحجم. قد يكون mov واحد أو movsd أو movsd متبوعا movsb، حسب الحاجة.

يبدو أنه إذا كنت ترغب حقا في استخدام movsb أو movsd دائما، حتى مع حجم "ديناميكي"، فسيتعين علي استخدام التجميع المضمن أو جوهري خاص (انظر أدناه). أعرف أن الحجم هو "قصير جدا"، لكن المترجم لا يعرف ذلك ولا أستطيع توصيل هذا الأمر - حتى حاولت استخدام __assume (الحجم <16)، لكنه لا يكفي.

الرمز التوضيحي، ترجمة مع "-OB1 (التوسع إلى مضمنة فقط):

  #include <memory.h>

  void MemCpyTest(void *tgt, const void *src, size_t size)
  {
    memcpy(tgt,src,size);
  }

  template <int size>
  void MemCpyTestT(void *tgt, const void *src)
  {
    memcpy(tgt,src,size);
  }

  int main ( int argc, char **argv )
  {
    int src;
    int dst;
    MemCpyTest(&dst,&src,sizeof(dst));
    MemCpyTestT<sizeof(dst)>(&dst,&src);
    return 0;
  }

جوهري متخصص

لقد وجدت مؤخرا هناك طريقة بسيطة للغاية كيفية جعل أحرف نسخ مترجم Visual Studio المرئي باستخدام Movsd - طبيعي للغاية وبسيط: باستخدام جوهري. بعد جوهري قد يأتي مفيد:

نصائح أخرى

العديد من الأسئلة تتبادر إلى الذهن.

أولا، كيف تعرف Movsd سيكون أسرع؟ هل نظرت إلى رفع الكمون / الإنتاجية؟ بنية X86 مليئة بالتعليمات القديمة Crufty التي لا ينبغي استخدامها لأنها ليست فعالة للغاية على وحدة المعالجة المركزية الحديثة.

ثانيا، ماذا يحدث إذا كنت تستخدم std::copy بدلا من memcpy؟ std::copy من المحتمل أن تكون أسرع، حيث يمكن التخصص في وقت الترجمة لنوع البيانات المحددة.

وثالثا، هل قمت بتمكين الوظائف الجوهرية ضمن خصائص المشروع -> C / C ++ -> التحسين؟

بالطبع أفترض أنه يتم تمكين التحسينات الأخرى أيضا.

هل تقوم بتشغيل بناء محسن؟ لن يستخدم جوهريا ما لم يكن الأمثل قيد التشغيل. تجدر الإشارة أيضا إلى أنه من المحتمل أن تستخدم حلقة نسخ أفضل من REP MOVSD. يجب أن نحاول استخدام MMX، على الأقل، لأداء 64 بت في نسخة زمنية. في الواقع 6 أو 7 سنوات، كتبت حلقة نسخة محسنة MMX للقيام بهذا النوع من الأشياء. لسوء الحظ، تفوقت MAMCPy المترجم الرائعة على نسخة MMX الخاصة بي بحوالي 1٪. أن علمنا حقا عدم اتخاذ افتراضات حول ما يفعله المحول البرمجي.

هل توقيت memcpy؟ في الإصدارات الحديثة من Visual Studio، يستخدم تطبيق MEMCPY SSE2 ... الذي يجب أن يكون أسرع من rep movsd. وبعد إذا كانت كتلة النسخ التي تناسبها هي 1 كيلو بايت، فهي ليست مشكلة حقا أن المحول البرمجي لا يستخدم جوهريا لأن وقت استدعاء الوظيفة سيكون ضئيلا مقارنة بالوقت المناسب للنسخة.

لاحظ أنه من أجل الاستخدام movsd, src يجب الإشارة إلى الذاكرة المحاذاة إلى حدود 32 بت وطول طوله يجب أن يكون مضاعفا من 4 بايت.

إذا كان الأمر كذلك، فلماذا استخدام التعليمات البرمجية الخاصة بك char * بدلا من int * أو شيء ما؟ إذا لم يكن الأمر كذلك، فإن سؤالك هو Moot.

إذا قمت بتغيير char * ل int *, ، أنت ربما الحصول على نتيجة أفضل من std::copy.

يحرر: هل قمت بقياس أن النسخ هو عنق الزجاجة؟

استخدام memcpy.هذه المشكلة قد تم حلها.

لمعلوماتك مندوب movsd ليست دائما أفضل ، rep movsb يمكن أن يكون أسرع في بعض الظروف و مع SSE و الأفضل هو movntq [edi], xmm0.حتى يمكنك تحسين زيادة على كمية كبيرة من الذاكرة في استخدام صفحة محلة طريق نقل البيانات إلى المخزن المؤقت ثم نقله إلى الوجهة الخاص بك.

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