Как кешировать чтения?

Я использую 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) :-)

Другие вопросы по тегам