سؤال

تحرير: تنطبق هذه المشكلة فقط على أنظمة 32 بت فقط. إذا كانت جهاز الكمبيوتر الخاص بك، فإن نظام التشغيل الخاص بك وتنفيذ Python الخاص بك هو 64 بت، ثم تعمل الملفات الضخمة MMP-ING بشكل موثوق وفعال للغاية.

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

في ذلك الوقت كتبت فئة التفاف الخاصة بي لم أكن أعرف عن MMP الوحدة. وبعد عند قراءة الوثائق ل MMAP اعتقدت "رائع - هذا هو ما كنت بحاجة فقط، سآخذ الرمز الخاص بي واستبدله ب MMAP. ربما يكون أكثر كفاءة للغاية وهو دائما جيد لحذف التعليمات البرمجية."

المشكلة هي أن mmap لا يعمل من أجل ملفات كبيرة! هذا مفاجئ جدا بالنسبة لي كما اعتقدت أنه ربما كان التطبيق الأكثر وضوحا. إذا كان الملف أعلى عدد قليل من جيجابايت، أحصل على EnvironmentError: [Errno 12] Cannot allocate memory. وبعد يحدث هذا فقط ببناء بيثون 32 بت، لذلك يبدو أنه ينفد من مساحة العنوان، لكن لا يمكنني العثور على أي وثائق حول هذا الموضوع.

الرمز الخاص بي هو فقط

f = open('somelargefile', 'rb')
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

لذلك سؤالي هو هل أفتقد شيئا واضحا هنا؟ هل هناك طريقة للحصول على MMAP للعمل المحدد على الملفات الكبيرة أم أنه يجب أن أعود إلى مجمع ملف Naïve الخاص بي؟


تحديث: يبدو أن هناك شعور بأن Python MMAP يجب أن يكون له نفس القيود مثل posix mmap. لتحسين التعبير عن إحباطي هنا هي فئة بسيطة لها جزء صغير من وظيفة MMAP.

import os

class Mmap(object):
    def __init__(self, f):
        """Initialise with a file object."""
        self.source = f

    def __getitem__(self, key):
        try:
            # A slice
            self.source.seek(key.start, os.SEEK_SET)
            return self.source.read(key.stop - key.start)
        except AttributeError:
            # single element
            self.source.seek(key, os.SEEK_SET)
            return self.source.read(1)

من القراءة فقط ولا تفعل أي شيء يتوهم، ولكن يمكنني القيام بذلك تماما كما هو الحال مع MMAP:

map2 = Mmap(f)
print map2[0:10]
print map2[10000000000:10000000010]

إلا أنه لا توجد قيود على filesize. ليس من الصعب جدا حقا ...

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

المحلول

من IEEE 1003.1:

يجب أن تقوم وظيفة MMAP () بإنشاء رسم خرائط بين "مساحة عنوان" العملية وملف أو كائن ذاكرة مشترك "أو [TYM] كائن الذاكرة المكتوبة.

يحتاج إلى كل مساحة العنوان الافتراضية لأن هذا هو بالضبط ما mmap() هل.

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

نصائح أخرى

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

لا تذكر وثائق Python Posix MMAP وهكذا إذا أتيت إليها كمبرمج ثعبان دون معرفة الكثير من المعرفة ب Posix (كما فعلت)، فستظهر مشكلة مساحة العنوان تعسفية للغاية ومصممة بشكل سيء!

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

يمكن لنظام التشغيل والتشغيل 32 بت فقط معالجة 32 بت كحد أقصى من الذاكرة IE 4GB. هناك عوامل أخرى تجعل المجموع أصغر؛ على سبيل المثال، يحتفظ بنظام Windows بين 0.5 و 2 جيجابايت للوصول إلى الأجهزة، وبالطبع سوف يستغرق البرنامج الخاص بك بعض المساحة أيضا.

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

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

النقطة التي تفتقدها هي أن MMP هي وظيفة رسم خرائط الذاكرة تقوم بتعيين ملف في الذاكرة للوصول التعسفي عبر نطاق البيانات المطلوب بأي وسيلة.

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

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

أنت تقوم بإعداد المعلمة الطول إلى الصفر، مما يعني الخريطة في الملف بأكمله. على بناء 32 بت، لن يكون هذا ممكنا إذا كان طول الملف أكثر من 2 جيجابايت (ربما 4 جيجابايت).

استخدم كمبيوتر 64 بت، مع نظام تشغيل 64 بت وتنفيذ Python 64 بت، أو تجنب mmap()

mmap() يستوجب دعم الأجهزة وحدة المعالجة المركزية له معنى مع ملفات كبيرة أكبر من عدد قليل من الجب.

يستخدم وحدة المعالجة المركزية MMU. ومقاطعة النظم الفرعية للسماح بتكشف البيانات كما لو كانت تم تحميل الكبش بالفعل.

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

هذا يجعل رمز الوصول الخاص بك سهلة الكتابة. ومع ذلك، لاستخدام mmap() بهذه الطريقة، سيحتاج كل شيء المعني إلى التعامل مع عناوين 64 بت.

وإلا فقد يكون من الأفضل تجنبه mmap() تماما وإجراء إدارة الذاكرة الخاصة بك.

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

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