Performance – What is the fastest way to apply functions on each line of matrix?

I have searched so far and I know there are several methods (1, 2, 3, 4) I have used the following code so far:

Fv_calc(:,2) = arrayfun(@(n) MaxPositiveRoot2DegreePolynomial(QuadraticCoefficients(n,:)), 1:size(QuadraticCoefficients,1));

Where MaxPositiveRoot2DegreePolynomial is the following function:

function root = MaxPositiveRoot2DegreePolynomial(c)
d = c./c(1);
root = eig([ 0 -d(3);1 -d(2)]);
condition = root == abs(root);
root = root(condition);
if isempty(root)
root = 0;
end
root = max(root);
end

Among them, QuadraticCoefficients is a 62271×3 matrix, and each row contains general two Coefficients a, b, c. ax ^ 2 bx c
About the problem I am solving, all the roots are real, so I use a modified function to find the roots so as not to waste time checking whether the roots are Real.
Through analyzing the code, I found that each run of the function MaxPositiveRoot2DegreePolynomial takes about 0.000047 seconds, and it takes about 2.914925371 seconds to run for 62271. But the code

Fv_calc(:, 2) = arrayfun(@(n) MaxPositiveRoot2DegreePolynomial(QuadraticCoefficients(n,:)), 1:size(QuadraticCoefficients,1));

It takes 3.198597803 to run. So about 0.283672431 It is done by arrayfun. I want to see if there is a way to reduce this time?

This is a perfect example, it shows where you should continue to use loops. I think The vectorized solution you want is ultimately slower than your loop method.

But it may depend on your Matlab version, because I have combined Matlab R2015b with optimzed JIT-Compiler

strong>Used together, in the old version, the vectorization method may be faster.

[n,~] = size(C);
%// division
d = bsxfun(@rdivide,C,C(:,1));
%// create blocks for eigen matrix block procession
X = ([zeros(n,1) ones (n,1) -d(:,3) -d(:,2)] ).'; %'
Y = reshape(X,2,[]);
%// use block processing to get eigenvalues ​​of blocks
rt = blockproc(Y,[2 2],@(x) eig(x.data) ).'; %'
%// check if eigen values ​​are real positives
condition = rt == abs(rt);
%// output filter
out = rt(condition);

benchmark

function [t] = bench()
%// load your data
DATA = load('matlab');
C = DATA.QuadraticCoefficients;< br />
% functions to compare
fcns = {
@() thewaywewalk(C);
@() sepideh(C);
};

% timeit
t = zeros(2,1);
for ii = 1:10;
t = t + cellfun(@timeit, fcns);
end
end

function out = thewaywewalk(C) %thewaywewalk
[n,~] = size(C);
d = bsxfun(@rdivide,C,C( :,1));
X = ([zeros(n,1) ones(n,1) -d(:,3) -d(:,2)] ).'; %'
Y = reshape(X,2,[]);
rt = blockproc(Y,[2 2],@(x) eig(x.data) ).'; %'
condition = rt == abs(rt);
out = rt(condition);
end
function out = sepideh(C) %sepideh
[n,~] = size(C );
out = zeros(n,1);
for ii = 1:n
c = C(ii,:);
d = c./c(1 );
rt = eig([0 -d(3);1 -d(2)]);
condition = rt == abs(rt);
rt = rt(condition );
if isempty(rt)
rt = 0;
end
rt = max(rt);
out(ii) = rt;
end
end
ans =

12.2086 %// thewaywewalk
9.2176 %// sepideh

I still don’t see the point of the if condition.

So far I have searched, and I know there are several ways (1, 2, 3, 4 ) So far I have used the following code:

Fv_calc(:,2) = arrayfun(@(n) MaxPositiveRoot2DegreePolynomial(QuadraticCoefficients(n,:)), 1:size(QuadraticCoefficients,1));

Among them MaxPositiveRoot2DegreePolynomial is the following function:

function root = MaxPositiveRoot2DegreePolynomial(c)
d = c./c(1);
root = eig([0 -d(3);1 -d(2)]);
condition = root == abs(root);
root = root(condition);
if isempty(root)
root = 0;
end
root = max(root);
end

Among them, QuadraticCoefficients is a 62271×3 matrix, each row contains the coefficients a, b, c of the general quadratic equation. ax ^ 2 bx c
About the problem I am solving, all the roots are real, Therefore I use a modified function to find the root so as not to waste time checking whether the root is true.
By analyzing the code, I found that the function MaxPositiveRoot2DegreePolynomial takes about 0.000047 seconds for each run, and about 2.914925371 seconds for the 62271 run. But the code< /p>

Fv_calc(:,2) = arrayfun(@(n) MaxPositiveRoot2DegreePolynomial(QuadraticCoefficients(n,:)), 1:size(QuadraticCoefficients,1));

It takes 3.198597803 to run. So about 0.283672431 is created by a This is done by rrayfun. I want to see if there is a way to reduce this time?

This is a perfect example, it shows where you should continue to use loops. The vectorized solution I want is ultimately better than your loop method Slow.

But it may depend on your Matlab version, because I have used Matlab R2015b with optimzed JIT-Compiler, in the old version, vectorized The method may be faster.

[n,~] = size(C);
%// division
d = bsxfun(@rdivide,C ,C(:,1));
%// create blocks for eigen matrix block procession
X = ([zeros(n,1) ones(n,1) -d(:,3) -d(:,2)] ).'; %'
Y = reshape(X,2,[]);
%// use block processing to get eigenvalues ​​of blocks
rt = blockproc(Y,[2 2],@(x) eig(x.data) ).'; %'
%// check if eigen values ​​are real positives
condition = rt == abs (rt);
%// output filter
out = rt(condition);

benchmark

function [t] = bench()
%// load your data
DATA = load('matlab');
C = DATA.QuadraticCoefficients;

% functions to compare< br /> fcns = {
@() thewaywewalk(C);
@() sepideh(C);
};

% timeit
t = zeros(2,1);
for ii = 1:10;
t = t + cellfun(@timeit, fcns);
end
end

function out = thewaywewalk(C) %thewaywewalk
[n,~] = size(C);
d = bsxfun(@rdivide,C,C(:,1));
X = ([zeros(n,1) ones(n ,1) -d(:,3) -d(:,2)] ).'; %'
Y = reshape(X,2,[]);
rt = blockproc(Y, [2 2],@(x) eig(x.data) ).'; %'
condition = rt == abs(rt);
out = rt(condition);
end
function out = sepideh(C) %sepideh
[n,~] = size(C);
out = zeros(n,1);
for ii = 1 :n
c = C(ii,:);
d = c./c(1);
rt = eig([0 -d(3);1 -d(2 )]);
condition = rt == abs(rt);
rt = rt(condition);
if isempty(rt)
rt = 0;
end
rt = max(rt);
out(ii) = rt;
end
end
ans =

12.2086 %// thewaywewalk
9.2176 %// sepideh

I still don’t see the point of the if condition.

Leave a Comment

Your email address will not be published.