Как кешировать чтения?
Я использую python/pysam для анализа данных секвенирования. В своем уроке ( pysam - интерфейс для чтения и записи файлов SAM) для помощника по команде говорится:
"Этот метод слишком медленный для обработки с высокой пропускной способностью. Если для чтения требуется обработка его сопряжением, работайте из файла, отсортированного по имени для чтения, или, что лучше, из кэша.'
Как бы вы "кеш чтения"?
3 ответа
Кэширование - это типичный подход для ускорения длительных операций. Он жертвует памятью ради скорости вычислений.
Предположим, у вас есть функция, которая при заданном наборе параметров всегда возвращает один и тот же результат. К сожалению, эта функция очень медленная, и вам нужно вызывать ее много раз, чтобы замедлить работу вашей программы.
Что вы могли бы сделать, это сохранить ограниченное количество комбинаций {параметры: результат} и пропустить свою логику каждый раз, когда функция вызывается с теми же параметрами.
Это грязный трюк, но довольно эффективный, особенно если комбинация параметров низкая по сравнению с функциональной скоростью.
В Python 3 для этого есть декоратор.
В Python 2 библиотека может помочь, но вам нужно немного больше работы.
AlignmentFile принимает в качестве первого аргумента:
filepath_or_object
Таким образом, вместо предоставления имени файла, вы можете предоставить объект, который поддерживает файловый интерфейс, то есть методы seek
, read
, tell
, При реализации класса для этого вы также можете реализовать кэширование на чтение, что, конечно, должно зависеть от текущей позиции курсора.
Если размер файла достаточно мал, чтобы он поместился в памяти, вы можете прочитать весь файл и работать с ним. io.BytesIO
объект, не нужно создавать свой собственный класс:
data = io.BytesIO(open('datafile','rb').read())
your_object = AlignmentFile(data, <other args>)
Я не уверен, что это сильно ускорит процесс, потому что я предполагаю, что современные операционные системы (я знаю, что Linux это сделает) делают доступ к файлам кэша. Так что, может быть, этого достаточно, чтобы положиться на это.
Я считаю, что другие ответы не касаются того, как на самом деле кэшировать чтение на практике.
Вот простой способ сделать это:
from collections import defaultdict
from pysam import AlignmentFile
def get_mate(read_pairs, read):
if read.qname not in read_pairs or not (read.is_read1 ^ read.is_read2):
return None
pos = 1 if read.is_read1 else 0
return read_pairs[read.qname][pos]
# maps QNAME to a read pair
read_pairs = defaultdict(lambda : [None, None])
fin = AlignmentFile("your_filepath")
for read in fin.fetch(your_chrom,your_start,your_stop):
if read.is_paired and (read.is_read1 ^ read.is_read2):
pos = 0 if read.is_read1 else 1
read_pairs[read.qname][pos] = read
## Now compare execution time of these two commands
your_read_mate = fin.mate(your_read) # pysam, non-cached
your_read_mate = get_mate(read_pairs, your_read) # cached
В котором операционное определение пары чтения таково (см . формат SAM ):
- Два чтения имеют одно и то же QNAME
- Каждое чтение имеет установленный флаг 0x1 (
read.is_paired
) - Каждое чтение имеет только один из флагов 0x40 (
read.is_read1
) или 0x80 (read.is_read2
) установить (исключающее ИЛИread.is_read1 ^ read.is_read2
проверяет это)
На моей машине с помощью ipython
%timeit
команда, я получаю
18.9 ms ± 510 µs
для некэшированного звонка и
854 ns ± 28.7 ns
для кэшированного вызова для данного чтения (для которого я знаю, что пара находится в
read_pairs
) :-)