رمز التصميم ليناسب ذاكرة التخزين المؤقت لوحدة المعالجة المركزية؟

StackOverflow https://stackoverflow.com/questions/1822295

سؤال

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

إذا كنت تعرف أي روابط جيدة تشرح التخزين المؤقت لوحدة المعالجة المركزية، فوجهني في هذا الاتجاه.

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

المحلول

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

وتحرير (لجعل بعض النقاط قليلا أكثر وضوحا):

وهناك CPU نموذجية لديها عدد من مخابئ مختلفة. وهناك معالج مكتبي الحديث وعادة ما يكون على الأقل 2 وغالبا 3 مستويات من ذاكرة التخزين المؤقت. من قبل (على الأقل تقريبا) اتفاق عالمي "المستوى 1" هو مخبأ "الأقرب" لعناصر التجهيز، والأرقام ترتفع من هناك (2 المستوى التالي، المستوى 3 بعد ذلك، الخ.)

في معظم الحالات، (على الأقل) يتم تقسيم ذاكرة التخزين المؤقت من المستوى 1 إلى نصفين: مخبأ تعليمات وبيانات ذاكرة التخزين المؤقت (إنتل 486 هو ما يقرب من استثناء وحيد هو الذي أنا على علم، مع ذاكرة واحد لكل من التعليمات والبيانات - ولكن حتى انها عفا عليها الزمن تماما وربما لا تستحق الكثير من التفكير)

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

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

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

وهذا له أيضا آثار لكيفية كتابة التعليمات البرمجية. إذا كان لديك حلقة مثل:

for i = 0 to whatever
   step1(data);
   step2(data);
   step3(data);
end for

وكنت أفضل عموما من التوتير أكبر عدد ممكن من الخطوات معا كما يمكنك أن <م> ما يصل الى مبلغ التي تناسب في ذاكرة التخزين المؤقت. في اللحظة التي تجاوز ذاكرة التخزين المؤقت، ويمكن أداء / ستنخفض بشكل كبير. إذا كان رمز للخطوة 3 أعلاه كبير بما فيه الكفاية أنه لا يصلح في ذاكرة التخزين المؤقت، وكنت أفضل حالا عموما كسر حلقة يصل الى قطعتين مثل هذا (إن أمكن):

for i = 0 to whatever
    step1(data);
    step2(data);
end for

for i = 0 to whatever
    step3(data);
end for

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

.

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

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

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

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

نصائح أخرى

وهنا رابط ل على مخابئ / تحسين الذاكرة عن طريق كريستر إريكسون (من إله الحرب I / II / III الشهرة). انها بضع سنوات من العمر لكنه ما زال مهم جدا.

ورقة مفيدة من شأنها أن أقول لك أكثر مما كنت تريد معرفته عن مخابئ هي ما كل مبرمج يجب معرفته عن ذاكرة التي كتبها أولريش دريبر. <وأ href = "http://books.google.com/books؟id=57UIPoLt3tkC&dq=hennessy+computer+architecture&printsec=frontcover&source=bn&hl=en&ei=iZ0YS7z_DJGQsgPBqsD8BA&sa=X&oi=book_result&ct=result&resnum=4&ved=0CBkQ6AEwAw#v=onepage&q=&f = كاذبة "يختلط =" noreferrer "> هينيسي يغطي بدقة جدا. وقد كتبت كريستر ومايك أكتون حفنة من الأشياء الجيدة حول هذا أيضا.

وأعتقد أن عليك أن تقلق أكثر عن بيانات ذاكرة التخزين المؤقت من مخبأ تعليمات - في تجربتي، dcache الأخطاء هي أكثر تواترا، أكثر إيلاما، وثابتة أكثر من المفيد.

تحديث:13/01/2014وفقًا لمصمم الرقائق الكبير هذا، أصبحت الأخطاء في ذاكرة التخزين المؤقت الآن هي العامل المهيمن بشكل كبير في أداء التعليمات البرمجية، لذا فقد عدنا بشكل أساسي إلى منتصف الثمانينيات وشريحة 286 السريعة من حيث اختناقات الأداء النسبي للتحميل والتخزين والأعداد الصحيحة الحسابية، وذاكرة التخزين المؤقت يخطئ.

دورة تدريبية مكثفة في الأجهزة الحديثة بواسطة Cliff Click @ Azul . . . . .

--- نعيدك الآن إلى برنامجك المقرر بانتظام ---

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

مثال:رسم الخرائط منخفض

فيما يلي مثال على التقنية التي استخدمتها لملاءمة البيانات في ذاكرة التخزين المؤقت للرقاقة التي لها فائدة للأغراض العامة.

كان لدي ناقل عائم مزدوج يبلغ طوله 1250 عنصرًا، وهو منحنى وبائي ذي ذيول طويلة جدًا.يحتوي الجزء "المثير للاهتمام" من المنحنى على حوالي 200 قيمة فريدة فقط، لكنني لم أرغب في أن يؤدي اختبار if() على الوجهين إلى حدوث فوضى في خط أنابيب وحدة المعالجة المركزية (وبالتالي الذيول الطويلة، والتي يمكن استخدامها كمشتركين الأكثر تطرفًا القيم التي سيظهرها كود مونت كارلو)، وكنت بحاجة إلى منطق تنبؤ الفرع لعشرات الاختبارات الشرطية الأخرى داخل "النقطة الفعالة" في الكود.

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

أدى هذا إلى تقليص متطلبات التخزين إلى 2 كيلو بايت للنسخ المزدوجة، و1250 بايت للاشتراكات ذات 8 بت.أدى هذا إلى تقليص 10000 بايت إلى 3298.نظرًا لأن البرنامج قضى 90% أو أكثر من وقته في هذه الحلقة الداخلية، لم يتم إخراج المتجهين أبدًا من ذاكرة التخزين المؤقت للبيانات التي يبلغ حجمها 8 كيلو بايت.ضاعف البرنامج أدائه على الفور.لقد تم ضرب هذا الرمز ~ 100 مليار مرة في عملية حساب قيمة OAS لأكثر من مليون قرض عقاري.

نظرًا لأن ذيول المنحنى نادرًا ما يتم لمسها، فمن المحتمل جدًا أن العناصر الوسطى 200-300 فقط من ناقل int الصغير تم الاحتفاظ بها بالفعل في ذاكرة التخزين المؤقت، إلى جانب 160-240 ضعفًا متوسطًا يمثل 1/8 من النسب المئوية للفائدة.لقد كانت زيادة ملحوظة في الأداء، تم إنجازها في فترة ما بعد الظهر، في برنامج قضيت أكثر من عام في تحسينه.

أتفق مع جيري، كما كانت تجربتي أيضًا، على أن إمالة الكود نحو ذاكرة التخزين المؤقت للتعليمات لا يكاد يكون ناجحًا مثل تحسين ذاكرة التخزين المؤقت/البيانات.هذا هو أحد الأسباب التي تجعلني أعتقد أن ذاكرات التخزين المؤقت الشائعة لدى AMD ليست مفيدة مثل ذاكرات التخزين المؤقت للبيانات والتعليمات المنفصلة من Intel.أي:لا تريد الحصول على تعليمات تستهلك ذاكرة التخزين المؤقت، لأنها ليست مفيدة جدًا.ويرجع ذلك جزئيًا إلى أن مجموعات تعليمات CISC تم إنشاؤها في الأصل لتعويض الفرق الشاسع بين سرعة وحدة المعالجة المركزية وسرعات الذاكرة، وباستثناء الانحراف الذي حدث في أواخر الثمانينيات، كان هذا دائمًا صحيحًا إلى حد كبير.

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

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

لقد أصبح الأمر واضحًا بشكل مؤلم عندما كتبت بعض التعليمات البرمجية هنا على StackOverflow لعكس البتات في مصفوفة 4096 بت، والتي بعد أكثر من 30 عامًا من طرح الكمبيوتر الشخصي، لم تكرس المعالجات الدقيقة الكثير من الاهتمام أو الموارد للبتات، وآمل أن يحدث ذلك يتغير.على وجه الخصوص، أود أن أرى، بالنسبة للمبتدئين، أن النوع المنطقي يصبح نوع بيانات بت فعليًا في C/C++، بدلاً من البايت المسرف الذي يبعث على السخرية كما هو الحال حاليًا.

Hazwell's new Bit Manipulation Instructions

تحديث:29/12/2013

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

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

بالتفكير في هذا، ودراسة الكود، لفتت انتباهي بعض التفاصيل.

  1. تمت إضافة الطلبات الواردة إلى شريحة "الرأس" و"الملخص" في نفس الوقت، بجوار بعضها البعض في أسطر متجاورة من التعليمات البرمجية.

  2. عند تشغيل المؤقت، تم طرح الذيل من شريحة الملخص، وتركت النتائج في شريحة الملخص، كما تتوقع

  3. الوظيفة الثانية التي يتم استدعاؤها عند إطلاق المؤقت تقدم جميع المؤشرات التي تخدم الحلقة.بخاصة....يرتدي الرأس ذيلًا ، مما يشغل نفس موقع الذاكرة الذي احتل الذيل الجديد مواقع الذاكرة 512 التالية ، أو ملفوفة

  4. أراد المستخدم المزيد من المرونة في عدد الطلبات التي تتم إدارتها، من 512 إلى 4098، أو ربما أكثر.شعرت أن أقوى طريقة للقيام بذلك هي تخصيص 1000 شريحة زمنية وشريحة الملخص معًا ككتلة واحدة متجاورة من الذاكرة بحيث يكون من المستحيل أن ينتهي الأمر بشريحة الملخص بطول مختلف من شرائح الوقت الـ 1000 الأخرى.

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

لقد فعلت هذا بالضبط، ولكن بعد ذلك وجدت بعض التحسينات الإضافية في هذه العملية.لقد قمت بتغيير الكود الذي يحسب الملخص المتداول بحيث يترك النتائج في الذيل، بدلاً من شريحة الملخص.لماذا؟لأن الوظيفة التالية كانت تنفيذ memcpy() لنقل شريحة الملخص إلى الذاكرة التي يشغلها الذيل للتو.(غريب ولكنه حقيقي، الذيل يقود الرأس حتى نهاية الحلقة عندما يلتف).من خلال ترك نتائج الجمع في الذيل، لم أضطر إلى تنفيذ memcpy()، كان علي فقط تعيين pTail إلى pSummary.

بطريقة مماثلة، احتل الرأس الجديد موقع الذاكرة القديمة لشريحة الملخص التي لا معنى لها الآن، لذا مرة أخرى، قمت بتعيين pSummary إلى pHead، وقمت بصفر جميع قيمها باستخدام مجموعة memset إلى الصفر.

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

استخدم التصميم الأولي وحدات البايت لزيادة استخدام ذاكرة التخزين المؤقت إلى الحد الأقصى، ومع ذلك، تمكنت من تخفيف هذا القيد - تلبية طلب المستخدمين للتعامل مع أعداد أعلى من الموارد لكل مستخدم في كل مللي ثانية - لاستخدام السراويل القصيرة غير الموقعة وSTILL أداء مزدوج, ، لأنه حتى مع وجود 3 متجهات متجاورة مكونة من 512 اختصارًا غير موقع، يمكن لذاكرة التخزين المؤقت للبيانات سعة 32 كيلو بايت في ذاكرة التخزين المؤقت L1 أن تحتوي بسهولة على 3720 بايت المطلوبة، ثلثيها في المواقع المستخدمة للتو.فقط عندما يكون الذيل أو الملخص أو الرأس ملفوفًا بواحد من الثلاثة مفصولين بأي "خطوة" مهمة في ذاكرة التخزين المؤقت L3 بسعة 8 ميجابايت.

يبلغ إجمالي مساحة ذاكرة وقت التشغيل لهذا الرمز أقل من 2 ميجابايت، لذلك يتم تشغيله بالكامل من ذاكرة التخزين المؤقت على الشريحة، وحتى على شريحة i7 ذات 4 مراكز، يمكن تشغيل 4 مثيلات من هذه العملية دون أي تدهور في الأداء على الإطلاق ، ويرتفع إجمالي الإنتاجية قليلاً مع تشغيل 5 عمليات.إنها Opus Magnum فيما يتعلق باستخدام ذاكرة التخزين المؤقت.

ومعظم المجمعين C / C ++ تفضل لتحسين لحجم بدلا من "السرعة". وهذا هو، رمز أصغر ينفذ عادة أسرع من التعليمات البرمجية بسطه لما لها من آثار ذاكرة التخزين المؤقت.

لو كنت مكانك، كنت سأتأكد من أنني أعرف أي أجزاء من التعليمات البرمجية هي نقاط فعالة، والتي أعرّفها على أنها

  • حلقة ضيقة لا تحتوي على أي استدعاءات دالة، لأنها إذا استدعت أي دالة، فإن الكمبيوتر سيقضي معظم وقته في تلك الوظيفة،
  • يمثل جزءًا كبيرًا من وقت التنفيذ (مثل >= 10%) والذي يمكنك تحديده من خلال ملف التعريف.(لقد قمت فقط بتجربة المكدس يدويًا.)

إذا كان لديك نقطة اتصال كهذه، فيجب أن تتناسب مع ذاكرة التخزين المؤقت.لست متأكدًا من كيفية إخباره بذلك، لكني أظن أنه تلقائي.

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