Правильный способ кешировать только некоторые методы класса с помощью joblib

Я пишу класс, который имеет некоторые вычислительные методы и некоторые параметры, которые пользователь захочет настраивать итеративно и не зависит от вычислений.

Фактическое использование для визуализации, но вот пример мультфильма:

class MyClass(object):

    def __init__(self, x, name, mem=None):

        self.x = x
        self.name = name
        if mem is not None:
            self.square = mem.cache(self.square)

    def square(self, x):
        """This is the 'computation heavy' method."""
        return x ** 2

    def report(self):
        """Use the results of the computation and a tweakable parameter."""
        print "Here you go, %s" % self.name
        return self.square(self.x)

Основная идея заключается в том, что пользователь может захотеть создать много экземпляров этого класса с одинаковыми x но разные name параметры. Я хочу позволить пользователю предоставить joblib.Memory объект, который будет кэшировать часть вычислений, чтобы они могли "сообщать" множество разных имен без повторного вычисления квадратного массива каждый раз.

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

def myfunc(x, name, mem=None):
    theclass = MyClass(x, name, mem)
    theclass.report()

Но давайте пока проигнорируем это).


Следуя документам JobLib, я кеширую square функция с линией self.square = mem.cache(self.square), Проблема в том, что, потому что self будет отличаться для разных экземпляров, массив будет пересчитываться каждый раз, даже если аргумент один и тот же.

Я предполагаю, что правильный способ справиться с этим - изменить строку на

self.square = mem.cache(self.square, ignore=["self"])

Однако есть ли недостатки этого подхода? Есть ли лучший способ выполнить кэширование?

1 ответ

Из документов,

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

Поскольку вы хотите, чтобы кэширование памяти было необязательным, я рекомендую что-то вроде этого:

def square_function(x):
    """This is the 'computation heavy' method."""
    print '    square_function is executing, not using cached result.'
    return x ** 2

class MyClass(object):

    def __init__(self, x, name, mem=None):
        self.x = x
        self.name = name
        if mem is not None:
            self._square_function = mem.cache(square_function)
        else:
            self._square_function = square_function

    def square(self, x):
        return self._square_function(x)

    def report(self):
        print "Here you go, %s" % self.name
        return self.square(self.x)


from tempfile import mkdtemp
cachedir = mkdtemp()

from joblib import Memory
memory = Memory(cachedir=cachedir, verbose=0)

objects = [
    MyClass(42, 'Alice (cache)', memory),
    MyClass(42, 'Bob (cache)', memory),
    MyClass(42, 'Charlie (no cache)')
]

for obj in objects:
    print obj.report()

Исполнение дает:

Here you go, Alice (cache)
    square_function is executing, not using cached result.
1764
Here you go, Bob (cache)
1764
Here you go, Charlie (no cache)
    square_function is executing, not using cached result.
1764
Другие вопросы по тегам