【问题标题】:Can you memoize a class method in MATLAB without having to add a wrapper method to the class?您可以在 MATLAB 中记住类方法而不必向类添加包装方法吗?
【发布时间】:2023-01-07 09:17:22
【问题描述】:

假设您在 MATLAB 中有一个要记忆的类方法,以便缓存以前计算的结果,从而节省计算时间。 MATLAB 有一个内置的memoize 函数,但文档只关注将此函数应用于普通 MATLAB 函数。从版本 R2022b 开始,文档不提供有关类方法记忆的指导。

一种可行的方法是采用原始的公共类方法,重命名它,将其设为私有或受保护以将其隐藏在类的公共接口中,并创建一个新方法,它只是一个具有原始方法名称和路由方法调用的包装器到隐藏的原始类方法的记忆版本。

classdef SomeClass < handle
    methods
        function returnValue = MemoizedVersionOfClassMethod(this, args)
            memoizedMethod = memoize(@NonMemoizedVersionOfClassMethod);
            returnValue = memoizedMethod(this, args);
        end
    end

    methods (Access = protected)
        function returnValue = NonMemoizedVersionOfClassMethod(this, args)
            returnValue = % do some expensive computation here
        end
    end
end

有没有另一种方法可以避免为每个记忆类方法创建包装器方法?

有一个现有的(未回答的)问题 (Memoize a method of a class in matlab) 询问如何记忆类方法。我上面的代码提供了一个解决方案,但我不确定它是好的解决方案。这是否可以通过避免伴随这种方法的包装方法激增的方式来完成?

【问题讨论】:

  • 一个优雅的答案是可以为一组方法设置的 memoize 属性。 (例如:(Access = public, Memoizable = true)),这当然不存在。您当前的解决方案实际上对我来说相当正确。根据问题的不同,我可能采取的另一种选择是记住该方法的相关内容。一个银河大脑解决方案是编写一个类名MemoizeWrapper,其中包含要作为私有属性记忆的类的副本,并使用一些 [mumble] 动态方法名称解释传递方法调用。 (可能很有趣,但想法很糟糕。)

标签: matlab oop memoization


【解决方案1】:

好吧,在坐了一天之后,似乎可以一次记住一个类中的所有方法,而不是一次记住一个方法的笨拙感觉。

下面设置好memoizeTest类后,我们可以通过三种方式调用同一个WorkingMethod

  1. 一个简单的方法调用(这可以被保护,取决于所需的用途)
  2. 使用 OP 中的方法记忆
  3. 使用添加到类中的通用功能进行记忆

    它将像这样使用:

    >> m = memoizeTest();
    >> m.WorkingMethod([1 2 3])
    ans =
         6
    >> m.MemoizedMethod([1 2 3])
    ans =
         6
    >> m.memoized('WorkingMethod', [1 2 3])
    ans =
         6
    

    我并不是说这是个好主意。根据使用情况,我想测试的一些问题包括:

    • 如果方法调用试图改变对象的状态,这会如何表现
    • 对 each 方法调用使用字符串时性能有何影响。

    如果你真的想发疯,你可以尝试将通用记忆化实现为一个单独的类,然后使用 Matlab 的多重继承功能。 (我没有试过这个,但看起来它会起作用。)

    示例代码在这里:

    classdef memoizeTest < handle
        
        methods (Access = public)
            %This is the original solution.
            %    This works, but feel clunky if you need to memoize a lot of
            %    methods
            function returnValue = MemoizedMethod(self, args)
                memoizedMethod = memoize(@WorkingMethod);
                returnValue = memoizedMethod(self, args);
            end
        end
        
        
        methods (Access = public)
            %This is the actual, working method we want to memoize
            function returnValue = WorkingMethod(self, args)
                %Pretend this line is slow :)
                returnValue = sum(args);
            end
        end
        
        
        %%%% General memoization
        %    The code below should memoize ALL methods in the class, at the
        %    cost of a change to the calling syntax. The memoized methods need
        %    to be called using a string.
        properties (Access = private)
            %Add a class property to store our memoized methods
            memoizedMethods = containers.Map;
        end
        
        methods (Access = public)
            %Create a public method "memoized" with the following semantics:
            %
            %For an instance of this class X consider the following cases
            %    y1 = X.MethodName(inputs)
            %    y2 = X.memoized('MethodName', inputs)
            %y1 and y2 will return the same results, within the limits of the
            %"memoize" function.
            
            function out = memoized(self, strMethod, args)
                if  ismember(strMethod, methods(self))
                    
                    %For the first call with a particular method, create and
                    %memoize a function handle view of the method
                    if ~self.memoizedMethods.isKey(strMethod)
                        fn_method = @(varargin)self.(strMethod)(varargin{:});
                        fn = memoize(fn_method);
                        self.memoizedMethods(strMethod) = fn;
                    end
                    
                    %For all calls, get the store function handle out of
                    %storage, and use it.
                    fn = self.memoizedMethods(strMethod);
                    out = fn(args);
                    
                else
                    error(['No appropriate method, property ''' strMethod ''''])
                end
            end
        end
    end
    

【讨论】:

    猜你喜欢
    • 2016-04-08
    • 2011-06-02
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    相关资源
    最近更新 更多