ما الذي يقيسه تحديد ملفات تعريف C++ (أدوات أداء وحدة المعالجة المركزية من Google) بالضبط؟
-
05-07-2019 - |
سؤال
أحاول البدء باستخدام Google Perf Tools لتعريف بعض التطبيقات المكثفة لوحدة المعالجة المركزية (CPU).إنها عملية حسابية إحصائية تقوم بتفريغ كل خطوة إلى ملف باستخدام "ofstream".أنا لست خبيرًا في لغة C++، لذا أجد صعوبة في العثور على عنق الزجاجة.تمريرتي الأولى تعطي النتائج:
Total: 857 samples 357 41.7% 41.7% 357 41.7% _write$UNIX2003 134 15.6% 57.3% 134 15.6% _exp$fenv_access_off 109 12.7% 70.0% 276 32.2% scythe::dnorm 103 12.0% 82.0% 103 12.0% _log$fenv_access_off 58 6.8% 88.8% 58 6.8% scythe::const_matrix_forward_iterator::operator* 37 4.3% 93.1% 37 4.3% scythe::matrix_forward_iterator::operator* 15 1.8% 94.9% 47 5.5% std::transform 13 1.5% 96.4% 486 56.7% SliceStep::DoStep 10 1.2% 97.5% 10 1.2% 0x0002726c 5 0.6% 98.1% 5 0.6% 0x000271c7 5 0.6% 98.7% 5 0.6% _write$NOCANCEL$UNIX2003
وهذا أمر مثير للدهشة، حيث أن كل الحسابات الحقيقية تتم في SliceStep::DoStep.يبدو أن "_write$UNIX2003" (أين يمكنني معرفة ما هو هذا؟) يأتي من كتابة ملف الإخراج.الآن، ما يحيرني هو أنني إذا قمت بالتعليق على كل شيء outfile << "text"
البيانات وتشغيل pprof، 95٪ موجود SliceStep::DoStep
ويختفي `_write$UNIX2003'.ومع ذلك، لا يتم تسريع طلبي، مقاسًا بالوقت الإجمالي.كل شيء يسرع أقل من 1 بالمائة.
ماذا ينقصني؟
تمت الإضافة:إخراج pprof بدون outfile <<
البيانات هي:
Total: 790 samples 205 25.9% 25.9% 205 25.9% _exp$fenv_access_off 170 21.5% 47.5% 170 21.5% _log$fenv_access_off 162 20.5% 68.0% 437 55.3% scythe::dnorm 83 10.5% 78.5% 83 10.5% scythe::const_matrix_forward_iterator::operator* 70 8.9% 87.3% 70 8.9% scythe::matrix_forward_iterator::operator* 28 3.5% 90.9% 78 9.9% std::transform 26 3.3% 94.2% 26 3.3% 0x00027262 12 1.5% 95.7% 12 1.5% _write$NOCANCEL$UNIX2003 11 1.4% 97.1% 764 96.7% SliceStep::DoStep 9 1.1% 98.2% 9 1.1% 0x00027253 6 0.8% 99.0% 6 0.8% 0x000274a6
يبدو هذا كما كنت أتوقعه، باستثناء أنني لا أرى أي زيادة ملحوظة في الأداء (.1 ثانية في حساب 10 ثوانٍ).الكود هو في الأساس:
ofstream outfile("out.txt");
for loop:
SliceStep::DoStep()
outfile << 'result'
outfile.close()
تحديث:أقوم بالتوقيت باستخدام Boost::timer، بدءًا من حيث يبدأ ملف التعريف وينتهي حيث ينتهي.أنا لا أستخدم الخيوط أو أي شيء فاخر.
المحلول
من تعليقاتي:
تشير الأرقام التي تحصل عليها من ملف التعريف الخاص بك إلى أن البرنامج يجب أن يكون أسرع بحوالي 40% بدون بيانات الطباعة.
ومع ذلك، يبقى وقت التشغيل كما هو تقريبًا.
من الواضح أن أحد القياسات يجب أن يكون خاطئًا.وهذا يعني أن عليك إجراء قياسات أكثر وأفضل.
أقترح أولاً البدء بأداة سهلة أخرى:أمر الوقت.من المفترض أن يمنحك هذا فكرة تقريبية عن المكان الذي تقضي فيه وقتك.
إذا كانت النتائج لا تزال غير حاسمة، فأنت بحاجة إلى حالة اختبار أفضل:
- استخدم مشكلة أكبر
- قم بالإحماء قبل القياس.قم ببعض الحلقات وابدأ أي قياس بعد ذلك (في نفس العملية).
تيريستان:كل شيء في المستخدم.ما أفعله بسيط جدًا، على ما أعتقد.هل حقيقة أن الملف مفتوح طوال الوقت يعني أي شيء؟
وهذا يعني أن ملف التعريف خاطئ.
تؤدي طباعة 100000 سطر إلى وحدة التحكم باستخدام python إلى شيء مثل:
for i in xrange(100000):
print i
للتعزية:
time python print.py
[...]
real 0m2.370s
user 0m0.156s
sys 0m0.232s
عكس:
time python test.py > /dev/null
real 0m0.133s
user 0m0.116s
sys 0m0.008s
ما أود أن أشير له هو:قياساتك الداخلية و يظهر الوقت أنك لا تكسب أي شيء من تعطيل الإخراج.تقول أدوات Google Perf أنه يجب عليك ذلك.من المخطئ؟
نصائح أخرى
و_write $ UNIX2003 ربما في إشارة إلى استدعاء نظام write
POSIX، الذي النواتج إلى المحطة. I / O بطيء جدا بالمقارنة مع أي شيء آخر تقريبا، لذلك فمن المنطقي أن البرنامج تنفق الكثير من الوقت هناك إذا كنت تكتب عادلة قليلا من الانتاج.
ولست متأكدا لماذا البرنامج لا تسرع عند إزالة الإخراج، ولكن أنا لا يمكن أن تجعل حقا تخمين فقط على المعلومات التي قدمتها. سيكون من الجميل أن نرى بعض من رمز، أو حتى إخراج perftools عند إزالة بيان cout.
وperftools جوجل بجمع عينات من مكدس الاستدعاءات، لذلك ما عليك هو الحصول على بعض الوضوح في تلك.
ووفقا لوثيقة، يمكنك عرض الرسم البياني الدعوة في بيان أو عنوان التفاصيل. يجب أن أقول لك ما تحتاج إلى معرفته.