Python: медленная обработка миллиона записей - PullRequest
0 голосов
/ 29 января 2020

Я хочу обработать данные (содержащиеся в файле диска, позже загруженном в numpy.array экземпляр) с такими строками, как:

1 3 a
1 4 b
1 5 a
2 6 b

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

1  2
2  2
3  2
4  2
5  2
6  1

, где первый столбец - время начала, а второй столбец - количество идентификаторов

I написал следующий код, чтобы обработать его как:

j=[]                                          # a list of ids
for i in range( len( dataset1 ) ):
    indices = numpy.argwhere( ( dataset1[i,0] >= dataset[:,0] )
                            & ( dataset1[i,0] <= dataset[:,1] )
                              )
    j.append( len( set( dataset[indices[:,0],2] ) ) )

где:
- dataset1 имеет первый столбец как 1,2,3,4,5,6 временных меток и
- dataset имеет три столбца: время начала, время окончания и идентификатор.

Мне нужно обработать около 9 сотен миллионов строк, как указано в dataset1. Это очень медленно.

Я пытался распараллелить это как:

inputs = range( len( dataset1 ) )

def processInput( b ):
    indices = numpy.argwhere( ( b >= dataset[:,0] )
                            & ( b <= dataset[:,1] )
                              )
    return( len( set( dataset[indices[:,0],2] ) ) )

num_cores = 10

results = Parallel( n_jobs = num_cores )( delayed( processInput )( dataset[j,0] ) for j in inputs )

Но это все еще медленно. У меня есть еще 10 доступных ядер, но тогда диск становится узким местом.

Есть ли способ быстрой обработки этих данных?

1 Ответ

0 голосов
/ 29 января 2020

Q : Есть ли способ обработки этих данных fast ?

Да, есть.

(Python thread здесь немного не помогают, из-за GIL-блокировки (повторная сериализация всех усилий в чистом [SERIAL] последовательная обработка, с дополнительными накладными расходами для увеличения интенсивности поиска для получения GIL-блокировки), Python процесс параллелизм дорог, и реплицирует все данные RAM Включая itnerpreter столько раз, сколько один спрашивает (блокирует диск, потому что он меняет оперативную память, не из-за плавного считывания дорожки, а из-за некоторых < 1E9 строк данных в файле, конечно, если у вас нет нескольких - [ТБ] RAM-устройство для одновременного хранения всех python -процессов / копий данных))


Шаг 1:
Настройка эффективной поток данных в достаточно эффективную обработку

подготовить файл данных, чтобы наилучшим образом удовлетворить ваши дальнейшие тривиальные подсчеты id -s

sort -k1,1       \
     -k3          \
     --parallel=19 \
     --output=dataset1_SORTED_DATA.txt < dataset1_data_file.txt

sort --parallel=19 \
     --output=dataset_SORTED_GATEs.txt < dataset_T1_T2_GATEs_data_file.txt

Шаг 2:
последовательно обрабатывает отсортированный файл в соответствии со «стробирующим» чтением из 2-го файла

Первый dataset1_SORTED_DATA.txt файл следующий простой процесс (подсчет непрерывных последовательных блоков строк, соответствующих условиям), чтение это только один раз, последовательно, в соответствии с использованием также отсортированных < T1_start, T2_end > -gates, подготовленных во втором файле dataset_SORTED_GATEs.txt.

Это, почти потоковая обработка, является плавным и использует простой подсчет строк, которые удовлетворяют обоим условиям из файла данных ...SORTED_GATEs.txt, где < T1, T2 > -gates, снова монотонно растут все больше и больше, поэтому первый файл ...SORTED_DATA.txt обрабатывается за один плавный проход, считая только id -s, как было запрошено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...