Today, I'm going to focus on three new functions that were added to the MATLAB programming language in R2022a: allfinite, anynan and anymissing. These functions are more concise, and usually faster, than alternative methods

Are all matrix elements finite? Doing it the old way.

How do you check if all the elements of a matrix are finite or not? Here's a matrix where the answer is 'No' by design.

a=rand(3);a(2,2)=inf

A common pattern for testing if every element in a matrix is finite is to first apply the isfinite function which returns a logical array:

checkFinite = isfinite(a)

and then pass this to the all function which checks if all the entries of each column are true or not

checkAllRowsFinite = all(checkFinite)

we apply the all function one more time to get the result we want

checkAllFinite = all(checkAllRowsFinite)

No! All the entries of our original matrix are not finite! Usually, all of the above is put into one line:

checkAllFinite = all(all(isfinite(a)))

This was a common pattern for many years and things could get out of hand when dealing with multiple dimensional arrays. For example to check if every element of

a=rand(3,3,3,3);

is finite, we'd need to do

checkAllFinite = all(all(all(all(isfinite(a)))))

That's a lot of all! Some people use the concise but arguably cryptic

checkAllFinite = all(isfinite(a(:)))

So, in R2018b, we introduced a new way of doing this that's nicer to read

checkAllFinite = all(isfinite(a),'all')

New in R2022a: allfinite - Finding if all is finite, fast

We see these patterns a lot in both our code and user's code. So much so that in R2022a, we've developed another function to make it even easier to perform this common operation: allfinite

a = rand(3);a(2,2)=inf;

CheckAllFinite = allfinite(a)

We didn't do this just to save on typing though. We did it because it's faster! You see the biggest difference with a large number of small matrices. Let's look at 10 million 3 x 3 matrices.

a3 = rand(3);

tic

for i =1:1e7

tf = all(isfinite(a3), 'all');

end

oldMethodTime = toc

tic

for i =1:1e7

tf = allfinite(a3);

end

newMethodTime=toc

fprintf("allfinite(a3) is %.2f times faster than all(isfinite(a3), 'all') for " + ...

"10 million small matrices\n",oldMethodTime/newMethodTime)

That can add up to quite a difference in functions that are called a lot. The benefit is reduced for larger matrices but it's still useful

a2000 = rand(2000);

tic

for i =1:1e3

tf = all(isfinite(a2000), 'all');

end

oldMethodTime = toc

tic

for i =1:1e3

tf = allfinite(a2000);

end

newMethodTime=toc

fprintf("allfinite(a2000) is %.2f times faster than all(isfinite(a2000), 'all') for " + ...

"1000 large matrices\n",oldMethodTime/newMethodTime)

Are there any NaNs or is anything missing?

Along with allfinite, the MATLAB math team identified two other patterns that could be optimised in a similar way and came up with the functions anynan and anymissing. When working with arrays, there will almost always be a speedup although you may have to run it many times to see it.

B = 0./[-2 -1 0 1 2]

tic

repeats = 1e6;

for i =1:repeats

tf = any(isnan(B), 'all');

end

oldMethodTime = toc

tic

for i =1:repeats

tf = anynan(B);

end

newMethodTime=toc

fprintf("anynan(B) is %.2f times faster than any(isnan(B), 'all') for " + ...

"%d small vectors\n",oldMethodTime/newMethodTime,repeats)

Is anynan faster for all datatypes?

For some data types, you might not see a speedup but it will be, at worst, as good as existing methods. Consider this example for checking for missing values in a table

singleVar = single([1;3;5;7;9;11;13]);

cellstrVar = {'one';'three';'';'seven';'nine';'eleven';'thirteen'};

categoryVar = categorical({'red';'yellow';'blue';'violet';'';'ultraviolet';'orange'});

dateVar = [datetime(2015,1:7,15)]';

stringVar = ["a";"b";"c";"d";"e";"f";"g"];

mytable = table(singleVar,cellstrVar,categoryVar,dateVar,stringVar)

Previously, you might have checked this as follows

TF = any(ismissing(mytable),'all')

Now, we can do

TF = anymissing(mytable)

The times are about the same so we can safely use these new functions all the time. Let's run it 5000 times to see

tic

repeats = 5e3;

for i =1:repeats

tf = any(ismissing(mytable),'all');

end

oldMethodTime = toc

tic

for i =1:repeats

tf = anymissing(mytable);

end

newMethodTime=toc

We've started using these new functions straight away in many MATLAB functions. They're used in argument validation in functions like expm, logm and median among others. Take a look for yourself by looking at the source code with, for example

edit sqrtm

In a release as big as R2022a that has many shiny features, simple functions such as these can often get overlooked. They are, however, useful new ways of performing very common operations. Teams at MathWorks are already starting to use them thoughout the codebase to make improvements here and there and I am sure I'll get the chance to usefully use them in user's code soon enough.

Do you think they'll be useful in your workflow? Are there any similar functions you wish MATLAB had?

## 댓글

댓글을 남기려면 링크 를 클릭하여 MathWorks 계정에 로그인하거나 계정을 새로 만드십시오.