【问题标题】:Matlab parsing at run-time of function handlesMatlab在函数句柄运行时解析
【发布时间】:2017-01-25 22:23:28
【问题描述】:

我的问题:给定一个函数句柄,matlab 是在每次需要评估它时解析字符串,还是只解析一次然后缓存它?

示例

考虑巧妙的功能

function [] = foo(func)
for j=1:1e4
    func(j);
end

和脚本

func1 = @(x) 5*abs(x)^2
function foo(func1);

在运行时,Matlab 需要将@(x) 5*abs(x)^2 解释为一个函数。在这个例子中,它是做一次,还是做一千次?

【问题讨论】:

    标签: matlab runtime function-handle


    【解决方案1】:

    首先@(x)cos(x)不是一个字符串,它是一个anonymous function declaration。当您创建匿名函数时,MATLAB 实质上会创建一个函数对象,其中包含运行所需的所有信息。然后可以将此匿名函数传递给各种函数,甚至可以保存到文件中。因此,它只被构造一次并被多次评估。

    在求值时,MATLAB 不进行任何缓存,因此多次使用相同的输入调用相同的匿名函数会导致每次都求值匿名函数的内容。

    如果你想获得更多关于你的匿名函数的信息,包括函数的本地工作空间,你可以使用functions函数

    f = @(x)cos(x);
    
    functions(f)
    
    %            function: '@(x)cos(x)'
    %                type: 'anonymous'
    %                file: ''
    %           workspace: {[1x1 struct]}
    %    within_file_path: '__base_function'
    

    话虽如此,在您的示例中,它真的可以简化为 function handle 而不是匿名函数,因为您将所有输入参数直接传递给 cos 而无需修改它们。如您所见,它具有不同的内部表示,并且从一些初步基准测试来看,它似乎稍微快了一点。

    f = @cos
    
    functions(f)
    
    %    function: 'cos'
    %        type: 'simple'
    %        file: ''
    

    还有一个快速的基准测试

    function benchit
        fprintf('Anonymous function: %0.4f\n', timeit(@option1));
        fprintf('Function handle:    %0.4f\n', timeit(@option2));
    end
    
    function option2()
        f = @(x)cos(x);
        for k = 1:10000
            f(k);
        end
    end
    
    function option1()
        f = @cos;
        for k = 1:10000
            f(k);
        end
    end
    

    和结果(其实差别不大)

    Anonymous function: 0.0056
    Function handle:    0.0049
    

    还有一些事情

    • 创建匿名函数时,匿名函数声明仍必须遵守 MATLAB 的所有标准语法规则,否则将无法创建。例如,以下将在匿名函数 创建 期间抛出错误,因为它是无效的语法

      func = @(x)thing]
      

      错误:不平衡或意外的括号或括号。

    • 当您评估一个匿名函数时(在它成功创建之后),就像评估任何其他函数一样,匿名函数可能会抛出错误,而错误取决于输入。

      func = @(x) x + [1 2];
      
      func([3 4])
      %   4   6
      
      % Now we're going to pass an array that isn't 1 x 2
      func([5 6 7])
      

      矩阵尺寸必须一致。
      @(x)x+[1,2] 中的错误

    【讨论】:

    • functions 记录在案:https://www.mathworks.com/help/matlab/ref/functions.html - 但是仅建议用于调试。
    • @horchler Welp,不知道我为什么这么想。更新。谢谢。
    • @Suever 谢谢。几个跟进。 (a) 我明白为什么余弦是一个不好的例子,我将给出一个真正需要匿名函数的例子。 (b) 很多时候创建了一个匿名函数,但只有当你尝试评估或执行它时,它才会抛出一个无效的异常。尝试定义func2 = (x) dfadf9x)。那么,它为func2存储了什么样的函数呢?
    • @AmirSagiv 查看我上面的更新。就错误、问题等而言,它实际上与函数文件没有什么不同(“正确性”在传递变量之前是未知的),只是它是内联定义的。
    • @AmirSagiv 您是否通过在.m 文件中编写函数并进行比较来对其进行基准测试?调用函数(匿名或其他方式)而不是直接将其写入代码会产生开销。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多