سؤال

وقد سئل مؤخرا كيفية عمل ملف slurp في بايثون, ، واقترحت الإجابة المقبولة شيئًا مثل:

with open('x.txt') as x: f = x.read()

كيف يمكنني القيام بذلك لقراءة الملف وتحويل التمثيل النهائي للبيانات؟

على سبيل المثال، لدي ملف ثنائي بحجم 1 غيغابايت وهو عبارة عن مجموعة من العوامات الدقيقة المفردة معبأة كنهاية كبيرة وأريد تحويلها إلى نهاية صغيرة وتفريغها في مصفوفة numpy.فيما يلي الوظيفة التي كتبتها لإنجاز هذا وبعض التعليمات البرمجية الحقيقية التي تستدعيها.أنا أستعمل struct.unpack قم بإجراء التحويل endian وحاول تسريع كل شيء باستخدام mmap.

سؤالي إذن هو: هل أستخدم المشروب بشكل صحيح؟ mmap و struct.unpack؟هل هناك طريقة أنظف وأسرع للقيام بذلك؟ما لدي يعمل حاليًا، ولكنني أود حقًا أن أتعلم كيفية القيام بذلك بشكل أفضل.

شكرا لك مقدما!

#!/usr/bin/python
from struct import unpack
import mmap
import numpy as np

def mmapChannel(arrayName,  fileName,  channelNo,  line_count,  sample_count):
    """
    We need to read in the asf internal file and convert it into a numpy array.
    It is stored as a single row, and is binary. Thenumber of lines (rows), samples (columns),
    and channels all come from the .meta text file
    Also, internal format files are packed big endian, but most systems use little endian, so we need
    to make that conversion as well.
    Memory mapping seemed to improve the ingestion speed a bit
    """
    # memory-map the file, size 0 means whole file
    # length = line_count * sample_count * arrayName.itemsize
    print "\tMemory Mapping..."
    with open(fileName, "rb") as f:
        map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
        map.seek(channelNo*line_count*sample_count*arrayName.itemsize)

        for i in xrange(line_count*sample_count):
            arrayName[0, i] = unpack('>f', map.read(arrayName.itemsize) )[0]

        # Same method as above, just more verbose for the maintenance programmer.
        #        for i in xrange(line_count*sample_count): #row
        #            be_float = map.read(arrayName.itemsize) # arrayName.itemsize should be 4 for float32
        #            le_float = unpack('>f', be_float)[0] # > for big endian, < for little endian
        #            arrayName[0, i]= le_float

        map.close()
    return arrayName

print "Initializing the Amp HH HV, and Phase HH HV arrays..."
HHamp = np.ones((1,  line_count*sample_count),  dtype='float32')
HHphase = np.ones((1,  line_count*sample_count),  dtype='float32')
HVamp = np.ones((1,  line_count*sample_count),  dtype='float32')
HVphase = np.ones((1,  line_count*sample_count),  dtype='float32')



print "Ingesting HH_Amp..."
HHamp = mmapChannel(HHamp, 'ALPSRP042301700-P1.1__A.img',  0,  line_count,  sample_count)
print "Ingesting HH_phase..."
HHphase = mmapChannel(HHphase, 'ALPSRP042301700-P1.1__A.img',  1,  line_count,  sample_count)
print "Ingesting HV_AMP..."
HVamp = mmapChannel(HVamp, 'ALPSRP042301700-P1.1__A.img',  2,  line_count,  sample_count)
print "Ingesting HV_phase..."
HVphase = mmapChannel(HVphase, 'ALPSRP042301700-P1.1__A.img',  3,  line_count,  sample_count)

print "Reshaping...."
HHamp_orig = HHamp.reshape(line_count, -1)
HHphase_orig = HHphase.reshape(line_count, -1)
HVamp_orig = HVamp.reshape(line_count, -1)
HVphase_orig = HVphase.reshape(line_count, -1)
هل كانت مفيدة؟

المحلول

with open(fileName, "rb") as f:
  arrayName = numpy.fromfile(f, numpy.float32)
arrayName.byteswap(True)

من الصعب جدًا التغلب على السرعة والإيجاز؛-).للحصول على بايت مبادلة انظر هنا (ال True الحجة تعني "افعل ذلك في مكانه")؛انظر من الملف هنا.

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

if struct.pack('=f', 2.3) == struct.pack('<f', 2.3):
  arrayName.byteswap(True)

على سبيل المثال، استدعاء لـ byteswap مشروط باختبار القليل من endianness.

نصائح أخرى

Alex مارتيلي في الإجابة :

arr = numpy.fromfile(filename, numpy.dtype('>f4'))
# no byteswap is needed regardless of endianess of the machine

هل يمكن أن قارب صيد السمك معا ASM حل يستند استخدام CorePy . أتساءل ان كنت قد تكون قادرة على الحصول على ما يكفي من الأداء من أي جزء آخر من الخوارزمية الخاصة بك. I / O والتلاعب على قطع 1GB من البيانات سوف تستغرق بعض الوقت الطريقة التي سبق لك أن شريحة.

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

وأتوقع شيئا من هذا القبيل أن تكون أسرع

arrayName[0] = unpack('>'+'f'*line_count*sample_count, map.read(arrayName.itemsize*line_count*sample_count))

يرجى عدم استخدام map كاسم متغير

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