سؤال

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

تمت كتابة التطبيق بلغة C++ ويعمل على نظام التشغيل Windows XP.

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

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

المحلول

إذا كنت تقوم بمعالجة الصور الطبية، فمن المحتمل أنك تقوم بتخصيص كتل كبيرة في المرة الواحدة (512 × 512، صور بحجم 2 بايت لكل بكسل).سوف يعضك التجزئة إذا قمت بتخصيص كائنات أصغر بين تخصيصات مخازن الصورة.

إن كتابة مُخصص مخصص ليس بالضرورة أمرًا صعبًا بالنسبة لحالة الاستخدام المحددة هذه.يمكنك استخدام مُخصص C++ القياسي لكائن الصورة الخاص بك، ولكن بالنسبة للمخزن المؤقت للبيكسل، يمكنك استخدام التخصيص المخصص الذي تتم إدارته بالكامل داخل كائن الصورة الخاص بك.إليك مخططًا سريعًا وقذرًا:

  • استخدم مصفوفة ثابتة من البنيات، كل بنية لها:
    • قطعة صلبة من الذاكرة يمكنها الاحتفاظ بـ N من الصور - سيساعد التقسيم في التحكم في التجزئة - جرب N أوليًا من 5 أو نحو ذلك
    • مصفوفة متوازية من المنطقيات تشير إلى ما إذا كانت الصورة المقابلة قيد الاستخدام أم لا
  • للتخصيص، ابحث في المصفوفة عن مخزن مؤقت فارغ وقم بتعيين علمه
    • إذا لم يتم العثور على أي منها، قم بإلحاق بنية جديدة بنهاية المصفوفة
  • لإلغاء التخصيص، ابحث عن المخزن المؤقت المقابل في المصفوفة (المصفوفات) وقم بمسح العلامة المنطقية

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

نصائح أخرى

هناك أجوبة، لكن من الصعب أن تكون عامة دون معرفة تفاصيل المشكلة.

أفترض أن نظام التشغيل Windows XP هو 32 بت.

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

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

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

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

حظ سعيد!

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

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

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

ما ستصل إليه هنا هو حد نطاق العنوان الافتراضي، والذي يمنحك مع نظام التشغيل Windows 32b 2 جيجابايت على الأكثر.يجب أن تدرك أيضًا أن استخدام واجهة برمجة التطبيقات الرسومية مثل DirectX أو OpenGL سيستخدم أجزاء كبيرة من تلك الـ 2 جيجا بايت للمخزن المؤقت للإطارات والأنسجة والبيانات المشابهة.

من الصعب جدًا تحقيق 1.5-2 غيغابايت لتطبيق 32b.الطريقة الأكثر أناقة للقيام بذلك هي استخدام تطبيق 64b OS و64b.حتى مع نظام التشغيل 64b وتطبيق 32b، قد يكون هذا قابلاً للتطبيق إلى حد ما، طالما أنك تستخدمه LARGE_ADDRESS_AWARE.

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

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

انظر بعض الأفكار العامة حول هذا الموضوع هنا.

أعتقد أنك تستخدم شيئًا غير مُدار، لأنه في الأنظمة الأساسية المُدارة، يعتني النظام (مجمع البيانات المهملة) بالتجزئة.

بالنسبة لـ C/C++، يمكنك استخدام مُخصص آخر غير المُخصص الافتراضي.(كانت هناك بالفعل بعض المواضيع حول المخصصات في تدفق المكدس).

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

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

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

إذا كان بإمكانك عزل تلك الأماكن التي من المحتمل أن تخصص فيها كتلًا كبيرة تمامًا، فيمكنك (على نظام Windows) الاتصال مباشرة بـ VirtualAlloc بدلاً من المرور عبر مدير الذاكرة.سيؤدي هذا إلى تجنب التجزئة داخل مدير الذاكرة العادي.

يعد هذا حلاً سهلاً ولا يتطلب منك استخدام مدير ذاكرة مخصص.

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