Преобразование больших числовых массивов BCD в десятичные - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть файлы двоичных данных в диапазоне нескольких ГБ, которые я отображаю в памяти с помощью numpy. Начало каждого пакета данных содержит метку времени BCD. Где каждое шестнадцатеричное число закодировано в формате времени 0DDD: HH: MM: SS.ssss Мне нужно, чтобы эта метка времени была превращена в общее количество секунд текущего года.

Data Excerpt

Пример: Первая отметка времени 0x0261 1511 2604 6002 будет: 261: 15: 11: 26.046002 или

261*86400 + 15*3600 + 11*60 + 26.046002 =  22551986.046002

В настоящее время я делаю это, чтобы вычислить временные метки:

import numpy as np
rawData  = np.memmap('dataFile.bin',dtype='u1',mode='r') 
#findFrameStart returns the index to the start of each data packet   [0,384,768,...]
fidx = findFrameStart(rawData)

# Do lots of bit shifting and multiplying and type casting....
day1  = ((rawData[fidx  ]>>4)*10 + (rawData[fidx  ]&0x0F)).astype('f8')
day2  = ((rawData[fidx+1]>>4)*10 + (rawData[fidx+1]&0x0F)).astype('f8')
hour  = ((rawData[fidx+2]>>4)*10 + (rawData[fidx+2]&0x0F)).astype('f8')
mins  = ((rawData[fidx+3]>>4)*10 + (rawData[fidx+3]&0x0F)).astype('f8')
sec1  = ((rawData[fidx+4]>>4)*10 + (rawData[fidx+4]&0x0F)).astype('f8')
sec2  = ((rawData[fidx+5]>>4)*10 + (rawData[fidx+5]&0x0F)).astype('f8')
sec3  = ((rawData[fidx+6]>>4)*10 + (rawData[fidx+6]&0x0F)).astype('f8')
sec4  = ((rawData[fidx+7]>>4)*10 + (rawData[fidx+7]&0x0F)).astype('f8')
time  = (day1*100+day2)*86400 + hour*3600 + mins*60 + sec1 + sec2/100 + sec3/10000 + sec4/1000000

Обратите внимание, что мне пришлось разыграть каждую из промежуточных переменных (день1, день2 и т. Д.), Чтобы удвоить, чтобы time вычислил правильно.

Учитывая, что существует много кадров, fidx может быть довольно большим (~ 10e6 элементов или более). Это приводит к множеству математических операций, сдвигов битов, приведению и т. Д. В моем текущем методе. Пока что он работает нормально для меньшего тестового файла (~ 180 мс для файла данных 150 МБ). Тем не менее, я беспокоюсь о том, что при получении больших данных (4-5 ГБ) могут возникнуть проблемы с памятью для всех промежуточных массивов.

Поэтому, если возможно, я искал другой метод, который мог бы сократить некоторые накладные расходы. Операции от двоично-десятичного к десятичному аналогичны для каждого байта, поэтому, возможно, я должен быть в состоянии что-то перебрать и, возможно, преобразовать массив на месте ... по крайней мере, уменьшив объем памяти.

Буду признателен за любую помощь. К вашему сведению, я использую Python 3.7

1 Ответ

0 голосов
/ 09 ноября 2018

Я внес следующие изменения в свой код. Это изменяет массив time и устраняет необходимость во всех промежуточных массивах. Я не рассчитал результат, но он должен занимать меньше памяти.

time = np.zeros(fidx.shape,dtype='f8')
scale = np.array([8640000, 86400, 3600, 60, 1, .01, .0001, .000001],dtype='f8')
for ii,sf in enumerate(scale):
    time = time + ((rawData[fidx+ii]>>4)*10 + (rawData[fidx+ii]&0x0F))*sf    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...