[bug #68121] convert isequal to built-in function for performance
Nicholas Jankowski <[email protected]>
| Newsgroups | gmane.comp.gnu.octave.bugs |
|---|---|
| Message-ID | <[email protected]> |
Please use the bug tracker to post updates to a bug report. The mailing list is intended as a read-only notification stream. Info posted to this mailing list address won't appear in the tracker database where it is most useful.
Follow-up Comment #3, bug #68121 (group octave):
yes a builtin would be faster. but isequal needs to first do input error
checking, then type checking, then has comparisons rules for each type. have
you run the profiler to see if it's the call to isequal or the calling
overhead that is your biggest time sink?
(also, you are just doing binary comparisons, yes? isequal(M,N,P,...) is
apparently known to be very slow)
after isequal does the top level minimal input validation, checks to see that
you're comparing two numeric arrays, and that they are the same size, it then
runs:
m = (x == y);
tf = all (m(:));
-verabtim-
so it does a vectorized == on the whole array, no shortcutting there,
following by all which does shortcut. you can see that with something
exaggerated like:
+verbatim+
>> a = ones (1e8,1);
>> tic,all(a), toc
ans = 1
Elapsed time is 0.0662308 seconds.
>> a(end)=0;
>> tic,all(a), toc
ans = 0
Elapsed time is 0.0720389 seconds.
>> a(1) = 0;
>> tic,all(a), toc
ans = 0
Elapsed time is 0.000986814 seconds.
a==a has similar time to the full run of all.
>> tic,a==a; toc
Elapsed time is 0.0697119 seconds.
for something your array size:
>> M = randi([1 10],9)-1;
>> tic,for idx = 1:100, M==M;endfor,toc
Elapsed time is 0.000114918 seconds.
>> tic,for idx = 1:10000, all(M(:));endfor,toc
Elapsed time is 0.0353448 seconds.
>> tic,for idx = 1:10000, isequal(M,M);endfor,toc
Elapsed time is 0.374975 seconds.
so the base operation is about 10x faster than calling isequal.
peeking at the profiler for this case:
>> profile clear, profile on; tic,for idx = 1:10000, isequal(M,M);endfor,toc;
>> profile off; profshow
Elapsed time is 0.440732 seconds.
# Function Attr Time (s) Time (%) Calls
------------------------------------------------------------------
2 isequal 0.307 86.54 10000
7 class 0.010 2.83 20000
14 all 0.008 2.27 10000
6 binary == 0.007 2.10 20000
15 full 0.004 1.00 10000
8 strcmp 0.003 0.95 10000
3 nargin 0.003 0.87 20001
9 size_equal 0.003 0.79 10000
11 ischar 0.002 0.54 10000
12 isreal 0.002 0.53 10000
13 issparse 0.002 0.50 10000
10 isobject 0.002 0.46 10000
4 binary < 0.001 0.28 10001
5 binary - 0.001 0.22 10000
16 toc 0.000 0.11 1
17 profile 0.000 0.01 1
18 false 0.000 0.00 1
1 tic 0.000 0.00 1
19 __profiler_enable__ 0.000 0.00 1
octave:95> profexplore
Top
1) isequal: 10000 calls, 0.354 total, 0.307 self
2) toc: 1 calls, 0.000 total, 0.000 self
3) profile: 1 calls, 0.000 total, 0.000 self
4) tic: 1 calls, 0.000 total, 0.000 self
profexplore> 1
Top
isequal: 10000 calls, 0.354 total, 0.307 self
1) class: 20000 calls, 0.010 total, 0.010 self
2) all: 10000 calls, 0.008 total, 0.008 self
3) binary ==: 20000 calls, 0.007 total, 0.007 self
4) full: 10000 calls, 0.004 total, 0.004 self
5) strcmp: 10000 calls, 0.003 total, 0.003 self
6) nargin: 20000 calls, 0.003 total, 0.003 self
7) size_equal: 10000 calls, 0.003 total, 0.003 self
8) ischar: 10000 calls, 0.002 total, 0.002 self
9) isreal: 10000 calls, 0.002 total, 0.002 self
10) issparse: 10000 calls, 0.002 total, 0.002 self
11) isobject: 10000 calls, 0.002 total, 0.002 self
12) binary <: 10000 calls, 0.001 total, 0.001 self
13) binary -: 10000 calls, 0.001 total, 0.001 self
looks like 80-90% of the time is in function overhead.
unfortunately we don't have a detailed profiler that would go deeper onto
function self-time. we do know that 'calling overhead' is simply higher than
we'd like separate from initial m-code input checks.
(1) do you have sufficiently well controlled inputs to our isequal(M,N) call
that you can just do tf = all([M==N](:)) directly (i don't know if it would be
faster in 1 or 2 lines)? if so that might be the most immediate workaround for
isequal.
(2) it might be worth running the profiler on your full code to be sure it's
isequal itself taking up the time.
(3) you could write a simple cpp program that does a looped element by element
comparison with at shortcut on fail, compile it into a .oct file, and call
that instead of isequal, and see how that does. as long as (2) isn't the
problem, this should help quite a bit.
i mainly work in mcode, so someone else can comment on the typed c-code
internals.
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?68121>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
signature.asc
(application/pgp-signature, 228 B)
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQk97aszIMMAvLLwm6qLAuaBUf3TgUCaanjCwAKCRCqLAuaBUf3 TlNRAQCifznuc4ZPEFFJb4FRwK0gvVs1+hYNSZxtvTmDQPaEdAD+L1cBuWX+xAMS vj3DhIhEGYFpqxth/b4fpDXYaH/J0ww= =eu59 -----END PGP SIGNATURE-----