Несколько процессов совместно используют один кеш Joblib

Я использую Joblib для кэширования результатов ресурсоемкой функции в моем скрипте Python. Входные аргументы функции и возвращаемые значения представляют собой пустые массивы. Кэш отлично работает для одного запуска моего скрипта Python. Теперь я хочу запустить несколько параллельных запусков моего скрипта Python для подметания некоторых параметров в эксперименте. (Определение функции остается одинаковым для всех прогонов).

Есть ли способ разделить кэш joblib между несколькими параллельно работающими скриптами Python? Это позволит сэкономить много вычислений функций, которые повторяются в разных запусках, но не повторяются в одном запуске. Я не смог найти, возможно ли это в документации Joblib


person Neha Karanjkar    schedule 30.07.2014    source источник
comment
Если вы уже выполняете распараллеливание в одном прогоне вашего скрипта, я не думаю, что можно многого добиться, пытаясь также распараллелить несколько прогонов. Я полагаю, вы могли бы добиться большего успеха, повторно используя кеш из предыдущего запуска. Я никогда не пробовал этого, но я думаю, что вы могли бы сделать это, используя один и тот же объект joblib.Memory в последовательных запусках.   -  person ali_m    schedule 30.07.2014
comment
@ali_m: Один запуск распараллелен, но мне также нужно запустить несколько запусков параллельно, потому что каждый запуск занимает несколько дней, а у меня много ядер (я запускаю их в кластере). Если кеш joblib представляет собой файл, то кажется, что несколько процессов должны иметь к нему доступ... Я не знаю, как это сделать.   -  person Neha Karanjkar    schedule 30.07.2014
comment
Как выглядит использование вашего ядра, когда вы выполняете один прогон? Если вы уже используете все свои ядра в одном прогоне, то распараллеливание между прогонами также не принесет вам пользы — дополнительные рабочие потоки будут просто конкурировать за один и тот же набор ядер, и вы вполне можете увидеть снижение производительности из-за дополнительных затрат на многопоточность и борьбы с кешем. Возможно, имеет смысл просто распараллелить несколько прогонов, а не один прогон — таким образом вы потратите пропорционально меньше времени на создание и завершение потоков, а не на выполнение вычислений.   -  person ali_m    schedule 30.07.2014
comment
Если вы mem.cache повторяете функциональность, это должно работать из коробки. По крайней мере на одной машине с многопроцессорностью. Совсем другое дело в кластере из нескольких машин, не использующих совместно используемое дисковое пространство. Если они делят дисковое пространство, и вы помещаете туда кеш, я не понимаю, почему это не должно работать.   -  person eickenberg    schedule 30.07.2014
comment
@eickenberg... Спасибо!! :) Наверное, я использовал cachedir = mkdtemp(), поэтому раньше он не работал. Он работает до тех пор, пока один и тот же каталог используется обоими процессами для хранения кеша.   -  person Neha Karanjkar    schedule 31.07.2014
comment
@eickenberg, пожалуйста, напишите свой комментарий в качестве ответа, и я приму   -  person Neha Karanjkar    schedule 31.07.2014
comment
Рад, что помог, это очень полезно для рекуррентных функций, которым требуется значительно меньше времени для загрузки из кеша, чем для вычисления.   -  person eickenberg    schedule 31.07.2014


Ответы (1)


Укажите общий, фиксированный cachedir и украсьте функцию, которую вы хотите кэшировать, используя

from joblib import Memory
mem = Memory(cachedir=cachedir)

@mem.cache
def f(arguments):
    """do things"""
    pass

или просто

def g(arguments):
   pass

cached_g = mem.cache(g)

Затем, даже если вы работаете между процессами, между машинами, если все экземпляры вашей программы имеют доступ к cachedir, то общие вызовы функций могут быть прозрачно кэшированы там.

person eickenberg    schedule 31.07.2014
comment
Действительно, мы (команда разработчиков joblib) тщательно проектируем дисковое хранилище таким образом, чтобы оно было устойчивым к параллельному доступу (и в основном к параллельной записи). В качестве примечания: я предпочитаю второй синтаксис первому в приведенном выше ответе. - person Gael Varoquaux; 24.10.2015
comment
@GaelVaroquaux, не могли бы вы пояснить, почему вы предпочитаете последнее? У меня есть @mem.cache во всем моем веб-приложении Tornado, и мне интересно, есть ли причина, по которой я должен реорганизовать их в рекомендуемую альтернативу. Спасибо! - person Kevin Ghaboosi; 15.04.2016
comment
@GaelVaroquaux Кроме того, мне интересно, стоит ли украшать функцию для асинхронного доступа, например, использовать `@gen.coroutine``, если задача выборки занимает больше времени, чем обычно, и функция вызывается из конечной точки HTTP или чувствительного к задержке клиента. Спасибо! - person Kevin Ghaboosi; 15.04.2016
comment
Я думаю, что @-обозначение - это просто сокращенная версия второго. Таким образом, второй делает явным то, что означает украшение, и дает вам возможность не потерять исходную недекорированную функцию. Могут быть ситуации, особенно в интерактивных сеансах, когда из-за изменения имени работает только второй вариант. - person eickenberg; 16.04.2016
comment
@GaelVaroquaux Отвечаю спустя долгое время .... Когда вы говорите в основном о параллельной записи, что подразумевается под в основном. Любые важные ошибки? Они где-то задокументированы? Спасибо. - person Caleb; 07.12.2020