Каков наилучший способ загрузки нескольких файлов в память параллельно с использованием Python 3.6? - PullRequest
0 голосов
/ 23 мая 2018

У меня есть 6 больших файлов, каждый из которых содержит объект словаря, который я сохранил на жестком диске с помощью функции pickle.Загрузка всех их в последовательном порядке занимает около 600 секунд.Я хочу начать загружать их все одновременно, чтобы ускорить процесс.Предположим, что все они имеют одинаковый размер, я надеюсь загрузить их за 100 секунд.Я использовал multiprocessing и apply_async для загрузки каждого из них по отдельности, но он работает как последовательный.Это код, который я использовал, и он не работает.Код для 3 из этих файлов, но он будет одинаковым для шести из них.Я поместил третий файл на другой жесткий диск, чтобы убедиться, что ввод-вывод не ограничен.

def loadMaps():    
    start = timeit.default_timer()
    procs = []
    pool = Pool(3)
    pool.apply_async(load1(),)
    pool.apply_async(load2(),)
    pool.apply_async(load3(),)
    pool.close()
    pool.join()
    stop = timeit.default_timer()
    print('loadFiles takes in %.1f seconds' % (stop - start))

1 Ответ

0 голосов
/ 23 мая 2018

Если ваш код в основном ограничен IO и файлы находятся на нескольких дисках, вы могли бы иметь возможность ускорить его с помощью потоков:

import concurrent.futures
import pickle

def read_one(fname):
    with open(fname, 'rb') as f:
        return pickle.load(f)

def read_parallel(file_names):
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = [executor.submit(read_one, f) for f in file_names]
        return [fut.result() for fut in futures]

GIL не заставит операции ввода-вывода запускаться сериализованно, потому что Python последовательно освобождает его при выполнении ввода-вывода.

Несколько замечаний об альтернативах:

  • multiprocessing вряд ли поможетпотому что, хотя он гарантирует выполнение своей работы в нескольких процессах (и, следовательно, не содержит GIL), он также требует передачи содержимого между подпроцессом и основным процессом, что занимает дополнительное время.

  • asyncio вам совсем не поможет, поскольку изначально не поддерживает асинхронный доступ к файловой системе (как и популярные операционные системы).Хотя он может эмулировать его с потоками , эффект такой же, как в приведенном выше коде, только с гораздо большей церемонией.

  • Ни один из вариантов не ускорит загрузку шестифайлы в шесть раз.Учтите, что по крайней мере некоторое времени уходит на создание словарей, которые будут сериализованы GIL.Если вы действительно хотите ускорить запуск, лучше не создавать весь словарь заранее и переключиться на базу данных в файле , возможно, используя словарь для кэширования доступа к его содержимому.

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