开发者

MATLAB: Performance problem with anonymous functions

开发者 https://www.devze.com 2023-02-18 21:06 出处:网络
Optimizing my MATLAB code, 开发者_StackOverflow中文版I stumbled upon a weird problem regarding anonymous functions.

Optimizing my MATLAB code, 开发者_StackOverflow中文版I stumbled upon a weird problem regarding anonymous functions.

Like in this thread I realized, that sometimes anonymous functions are running really slow. But with minimal changes to the function, it runs as fast as subfunctions or nested functions.

I used this (simple) test file to reproduce the behaviour with Matlab R2010b under Windows 7 64-bit:

clear all; close all; clc;

% functions
fn1 = @(x) x^2;
fn2 = @(x) double(x^2);

% variables
x = linspace(-100,100,100000);
N = length(x);

%% anonymous function
y = zeros(1,N);
t = tic;
for i=1:N
    y(i) = fn1(x(i));
end
tm.anonymous_1 = toc(t);

%% anonymous function (modified)
y = zeros(1,N);
t = tic;
for i=1:N
    y(i) = fn2(x(i));
end
tm.anonymous_2 = toc(t);

%% print
tm

The results I got were:

tm = 

    anonymous_1: 1.0605
    anonymous_2: 0.1217

As you can see the first approach is about 10 times slower. I have no idea what triggers this speedup/slowdown. I tried different things, getting nearly the same (fast) timings:

fn2 = @(x) 1 * x^2;
fn2 = @(x) 0 + x^2;
fn2 = @(x) abs(x^2);
fn2 = @(x) x*x;

Before I start profiling all of my functions, I would like to know if anyone has an explanation for this behaviour?

P.S.: I know that "vectorized" approaches are much faster, but in my case a solver will be evaluating the function for each variable time step, so that is not an option.


It appears that in the case of 'fn2' the Matlab optimizer is able to inline the function, whereas it is unable to do so in the case of 'fn1'.

This probably has to do with what Matlab knows about the scalarity or complexity or structure of the argument and return value. It probably figures out that 'i' (the argument at the call-site) is necessarily scalar, real and non-strctured. Given a scalar argument it then tries to figure out the behaviour of the function. In the case of 'fn2' Matlab's optimizer statically determines that it can always fit all possible results of 'double()' into the target variable 'y(i)'. For some reason only known to the designers of the optimizer, Matlab is unable to come to the same conclusion for 'fn1'. Maybe there are some non-obvious corner-cases, or '^' lacks some piece of meta-data that the optimizer depends on. Anyway, the result is that in case of 'fn1' Matlab apparently re-evaluats the function at every iteration.

Anyway, statically optimizing dynamic languages is something of a black art in compiler design.


I believe that making the return type of a function independent of its argument's types makes it easier for Matlab to optimize. By the way, y = fn1(x); and y = fn2(x); have roughly the same proportion in terms of run time, so it's not the effect of arguments being scalar or complex.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号