سؤال

شهدت التالية سلوك غريب.لدي اثنين من الوظائف التي تفعل تقريبا نفس قياس عدد دورات يلزم للقيام عملية معينة.في وظيفة واحدة ، داخل حلقة زيادة متغير ؛ في الآخر لا يحدث شيء.المتغيرات هي متقلبة حتى لا يكون الأمثل بعيدا.هذه هي الوظائف:

unsigned int _osm_iterations=5000;

double osm_operation_time(){
    // volatile is used so that j will not be optimized, and ++ operation
    // will be done in each loop
    volatile unsigned int j=0;
    volatile unsigned int i;
    tsc_counter_t start_t, end_t;
    start_t = tsc_readCycles_C();
    for (i=0; i<_osm_iterations; i++){
       ++j;
    }
    end_t = tsc_readCycles_C();
    if (tsc_C2CI(start_t) ==0 || tsc_C2CI(end_t) ==0 || tsc_C2CI(start_t) >= tsc_C2CI(end_t))
         return -1;
    return (tsc_C2CI(end_t)-tsc_C2CI(start_t))/_osm_iterations;
}

double osm_empty_time(){
    volatile unsigned int i;
    volatile unsigned int j=0;
    tsc_counter_t start_t, end_t;
    start_t = tsc_readCycles_C();
    for (i=0; i<_osm_iterations; i++){
        ;
    }
    end_t = tsc_readCycles_C();
    if (tsc_C2CI(start_t) ==0 || tsc_C2CI(end_t) ==0 || tsc_C2CI(start_t) >= tsc_C2CI(end_t))
        return -1;
    return (tsc_C2CI(end_t)-tsc_C2CI(start_t))/_osm_iterations;
}

هناك بعض غير القياسية وظائف هناك ولكن أنا متأكد من أنك سوف إدارتها.

الأمر هو أول وظيفة يعود 4, بينما الوظيفة الثانية (التي من المفترض أن لا أقل) ترجع 6, على الرغم الثانية من الواضح أنها أقل من الأولى.

لا تجعل أي معنى لأي شخص ؟

في الواقع أنا أول وظيفة لذا أنا يمكن أن تقلل من حلقة علوية على قياس بلدي الثاني.هل لديك أي فكرة عن كيفية القيام بذلك (لأن هذا الأسلوب لا قطع ذلك) ؟

أنا على أوبونتو (64 بت أعتقد).

شكرا جزيلا.

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

المحلول

وأستطيع أن أرى أمرين هنا. واحد هو أن رمز للحلقات اثنين تبدو متطابقة. وثانيا، فإن المترجم ربما يدركون أن i متغير والمتغير j سوف يكون دائما نفس القيمة وتحسين واحد منهم بعيدا. يجب أن ننظر في الجمعية ولدت ونرى ما يحدث في الواقع.

وهناك نظرية أخرى هي أن التغيير إلى الجسم الداخلي للحلقة أثرت على cachability من قانون - وهذا يمكن أن يكون نقله عبر خطوط ذاكرة التخزين المؤقت أو بعض الشيء الآخر.

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

لرؤية الجمعية ولدت في دول مجلس التعاون الخليجي، تحديد الخيار مترجم -S :

<اقتباس فقرة>   

س: كيف يمكنني نظرة خاطفة على رمز التجميع   الناتجة عن دول مجلس التعاون الخليجي؟

     

س: كيف يمكنني إنشاء الملف حيث يمكنني   راجع التعليمات البرمجية C وجمعيتها   ترجمة معا؟

     

وA: استخدم -S (ملاحظة: العاصمة S) التبديل   لدول مجلس التعاون الخليجي، وأنها سوف تصدر في التجمع   الرمز إلى ملف بملحق .S.   على سبيل المثال، الأمر التالي:

     

ودول مجلس التعاون الخليجي -O2 -S -c foo.c

     

وسوف يغادر رمز التجميع ولدت   على foo.s الملف.

     

إذا كنت تريد أن ترى رمز C معا   مع الجمعية تم تحويله إلى،   استخدام سطر الأوامر مثل هذا:

     

ودول مجلس التعاون الخليجي -c -g -Wa، واحد، -ad [دول مجلس التعاون الخليجي الأخرى   خيارات] foo.c> foo.lst

     

والتي سوف إخراج الجمع   C قائمة التجمع / إلى ملف   foo.lst.

نصائح أخرى

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

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

وبما أنك ذكرت هذا كان 64 بت نظام التشغيل، فإنه من المؤكد تقريبا كل هذه القيم هي في سجلات، لأن هناك المزيد من السجلات في الهندسة المعمارية x86_64. بخلاف ذلك، أود أن أقول أداء العديد من التكرارات، ونرى كيف مستقرة على النتائج.

إذا كنت تحاول حقا لاختبار تشغيل قطعة من التعليمات البرمجية ("j++;" في هذه الحالة)، وكنت أفضل في الواقع قبالة القيام بما يلي:

1 / هل لأنها في اثنين التنفيذية منفصلة لأنه ليس هناك احتمال أن الموقف داخل قابل للتنفيذ قد تؤثر على التعليمات البرمجية.

و2 / تأكد من استخدام وحدة المعالجة المركزية الوقت بدلا من الوقت المنقضي (لست متأكدا ما "tsc_readCycles_C()" يمنحك). هذا هو لتجنب النتائج المخطئين من وحدة المعالجة المركزية تحميل مع مهام أخرى.

و3 / إيقاف الأمثل مترجم (على سبيل المثال، "gcc -O0") لضمان gcc لا يضع في أي الاشياء يتوهم أن من المحتمل أن تؤثر على النتائج.

و4 / أنت لا داعي للقلق بشأن volatile إذا كنت تستخدم النتيجة الفعلية، مثل وضع:

printf ("%d\n",j);

وبعد الحلقة، أو:

FILE *fx = fopen ("/dev/null","w");
fprintf (fx, "%d\n", j);
fclose (fx);

وإذا كنت لا تريد أي إخراج على الإطلاق. لا أستطيع أن أتذكر ما إذا كانت متقلبة و<م> اقتراح إلى مترجم أو القسري.

و5 / تكرارات من 5000 يبدو قليلا على الجانب المنخفض، حيث "الضوضاء" يمكن أن تؤثر على قراءات. ربما قيمة أعلى سيكون أفضل. هذا قد لا يكون مشكلة إذا كنت توقيت قطعة أكبر من رمز وقمت بتضمين فقط "j++;" كمكان حامل.

عندما أقوم بإجراء اختبارات مماثلة على هذا, أنا عادة:

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

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

scroll top