سؤال

أنا ترقية اللعبة التي كانت في الأصل مكتوبة على Win32 API, لينكس (حسنا, ترقية OS X ميناء Win32 ميناء لينكس).

لقد نفذت QueryPerformanceCounter من خلال إعطاء uSeconds منذ عملية بدء التشغيل:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

هذا إلى جانب QueryPerformanceFrequency() إعطاء ثابت 1000000 كما تردد ، يعمل بشكل جيد على الجهاز الخاص بي, مما يجعلني 64 بت متغير يحتوي على uSeconds لأن البرنامج عند تشغيله.

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

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

المحلول

ربما.ولكن لديك مشاكل أكبر. gettimeofday() يمكن أن يؤدي في أوقات غير صحيحة إذا كانت هناك عمليات على نظام تغيير توقيت (أي نتبد).على "طبيعية" لينكس, على الرغم من أنني أعتقد حل gettimeofday() هو 10us.ويمكن أن تقفز إلى الأمام والخلف الوقت ، وبالتالي ، على أساس العمليات قيد التشغيل على النظام الخاص بك.وهذا يجعل الإجابة على سؤالك لا.

يجب أن ننظر إلى clock_gettime(CLOCK_MONOTONIC) توقيت فترات.فإنه يعاني من عدة أقل القضايا بسبب أشياء مثل متعدد النظم الأساسية والخارجية ضبط الساعة.

أيضا, النظر في clock_getres() وظيفة.

نصائح أخرى

عالية الدقة, انخفاض النفقات العامة توقيت معالجات إنتل

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

لاحظ أن هذا هو عدد دورات وحدة المعالجة المركزية.على لينكس يمكنك الحصول على سرعة وحدة المعالجة المركزية من /proc/cpuinfo و تقسم على عدد الثواني.تحويل هذا إلى ضعف هو مفيد جدا.

عند تشغيل هذا على بلدي مربع ، أحصل على

11867927879484732
11867927879692217
it took this long to call printf: 207485

هنا إنتل المطور دليل أن يعطي طن من التفاصيل.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}

@برنار:

أنا يجب أن أعترف, معظم سبيل المثال ذهبت مباشرة فوق رأسي.فإنه لا يجمع ، يبدو للعمل ، على الرغم من.هل هذا آمن على SMP أنظمة أو سبيدستيب?

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

عموما كيف يعمل هو:

  • تعلن كتلة من التعليمات البرمجية إلى أن مجمع (ومتقلبة ، لذلك محسن سوف تترك وحدها).
  • تنفيذ CPUID التعليمات.بالإضافة إلى الحصول على بعض معلومات وحدة المعالجة المركزية (والتي لا تفعل أي شيء مع) فإنه مزامنة تنفيذ وحدة المعالجة المركزية العازلة بحيث أوقات لا تتأثر من أجل التنفيذ.
  • تنفيذ rdtsc (قراءة الزمني) التنفيذ.هذا جلب عدد من آلة دورات أعدموا منذ المعالج تم إعادة تعيين.هذا هو 64 بت القيمة حتى مع وحدة المعالجة المركزية الحالية سرعات وسوف يلتف حول كل 194 سنوات أو نحو ذلك.ومن المثير للاهتمام, في الأصل بنتيوم المرجعية ، وأشاروا إلى أنه يلتف حول كل 5800 سنوات أو نحو ذلك.
  • آخر زوجين من الخطوط تخزين القيم من السجلات في المتغيرات مرحبا و لو وضعوه في 64 بت قيمة الإرجاع.

الملاحظات:

  • من أجل التنفيذ يمكن أن يسبب نتائج غير صحيحة ، لذلك نقوم بتنفيذ "cpuid" التعليمات التي بالإضافة إلى إعطائك بعض المعلومات حول وحدة المعالجة المركزية أيضا مزامنة أي من أجل تنفيذ التعليمات.

  • معظم نظام التشغيل مزامنة العدادات على وحدات المعالجة المركزية عندما تبدأ حتى الجواب هو جيد في غضون بضع نانو ثانية.

  • السبات التعليق على الأرجح صحيح ، ولكن في الممارسة ربما لا يهتمون المواعيد عبر السبات الحدود.

  • فيما يتعلق سبيدستيب:أحدث إنتل وحدات المعالجة المركزية لتعويض السرعة التغييرات وإعادة تعديل العد.قمت بعمل فحص سريع على بعض المربعات في الشبكة وجدت واحدة فقط مربع لم يكن لديك:بنتيوم 3 تشغيل بعض القديم خادم قاعدة البيانات.(هذه هي لينكس مربعات ، لذا راجعت مع:grep constant_tsc /proc/cpuinfo)

  • أنا غير متأكد حول وحدات المعالجة المركزية AMD نحن في المقام الأول Intel المحل ، على الرغم من أنني أعرف بعض من مستوى منخفض نظم معلمو لم AMD التقييم.

نأمل أن يكون هذا يرضي فضولك, انها مثيرة للاهتمام و (IMHO) ودرس تحت مجال البرمجة.أنت تعرف عندما جيف جويل كانت الحديث حول ما إذا كان أو لم يكن مبرمج يجب أن نعرف C ؟ كنت يصرخ عليها "مرحبا ننسى أن ارتفاع مستوى ج الاشياء...المجمع هو ما يجب أن تعلم إذا كنت تريد أن تعرف ما هو الكمبيوتر تفعل!"

النبيذ هو في الواقع باستخدام gettimeofday() لتنفيذ QueryPerformanceCounter() وكما هو معروف أن تجعل العديد من ألعاب ويندوز تعمل على لينكس و ماك.

يبدأ http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

يؤدي إلى http://source.winehq.org/source/dlls/ntdll/time.c#L448

لذلك يقول ميكروثانية صراحة ، ولكن يقول القرار من ساعة النظام هو غير محدد.أعتقد القرار في هذا السياق يعني كيف أصغر كمية من أي وقت مضى وسوف تكون زيادة?

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

مثل غيرها من الناس قد اقترحت ، gettimeofday() سيئة بسبب ضبط الوقت يمكن أن يسبب الساعة الانحراف و التخلص من الحساب الخاص بك. clock_gettime(CLOCK_MONOTONIC) هو ما تريد ، clock_getres() سوف اقول لك دقة الخاص بك على مدار الساعة.

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

حصلت على هذا الجواب من عالية الدقة قياس الوقت و توقيت, الجزء الأول

هذا الجواب يذكر مشاكل مع عقارب الساعة تعديل.كل المشاكل التي تكفل وضع علامة وحدات المشاكل مع الوقت يجري تعديلها يتم حلها في C++11 مع <chrono> المكتبة.

الساعة std::chrono::steady_clock لا يضمن أن يتم تعديلها ، وعلاوة على ذلك فإنه سوف تقدم بمعدل ثابت بالنسبة إلى الوقت الحقيقي ، حتى التقنيات مثل سبيدستيب يجب أن لا تؤثر عليه.

يمكنك الحصول على typesafe الوحدات عن طريق تحويل إلى أحد std::chrono::duration التخصصات مثل std::chrono::microseconds.مع هذا النوع هناك أي غموض حول الوحدات المستخدمة من قبل القراد القيمة.لكن, نضع في اعتبارنا أن الساعة لا يكون بالضرورة هذا القرار.يمكنك تحويل مدة attoseconds دون الحاجة فعلا ساعة دقيقة.

من تجربتي و من ما قرأت عبر الإنترنت, الجواب هو "لا" ليست مضمونة.ذلك يعتمد على سرعة وحدة المعالجة المركزية, نظام التشغيل, نكهة من لينكس ، إلخ.

قراءة RDTSC لا يمكن الاعتماد عليها في أنظمة SMP ، لأن كل واحد يحافظ على وحدة المعالجة المركزية الخاصة ومكافحة كل عداد ليست مضمونة من قبل متزامنة مع الاحترام إلى آخر وحدة المعالجة المركزية.

أقترح عليك أن تحاول clock_gettime(CLOCK_REALTIME).Posix دليل يشير إلى أن هذا ينبغي أن تنفذ على جميع متوافقة مع الأنظمة.يمكن أن توفر نانوثانية العد ، ولكن ربما كنت سوف ترغب في التحقق clock_getres(CLOCK_REALTIME) على النظام الخاص بك لمعرفة ما الفعلي القرار.

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