comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: For-loop vs. Dimensional Juggling relative performance
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: For-loop vs. Dimensional Juggling relative performance [message #69724] Tue, 09 February 2010 18:54 Go to next message
cgguido is currently offline  cgguido
Messages: 195
Registered: August 2005
Senior Member
On Feb 8, 10:26 pm, Gray <grayliketheco...@gmail.com> wrote:
> Hi folks,
>
> I recently wrote my own version of SRCOR from the NASA Astrolib.  Just
> as a reminder, the program takes two lists of 2D coordinates and finds
> matches where the distance is less than some cutoff.  SRCOR uses a for-
> loop to step through the first list, comparing the distance of each
> coordinate-pair from every point in the second list.  My version uses
> matrix multiplication and dimensional juggling to avoid the for-loop.
>
> For n1 = 2143 and n2 = 2115, SRCOR is faster (0.16 seconds to my 0.53
> on my macbook); however, for n1 = 25 and n2 = 26, mine is faster
> (1.8e-4 seconds to 4.2e-4).  Is there any way to predict what kind of
> list sizes will be faster with each method, without making some random
> data and using brute force?
>
> The relevant code is:
>
> SRCOR (dcr2 is the cutoff, option eq 2 ignores the cutoff) -->
>
>  FOR i=0L,n1-1 DO BEGIN
>    xx = x1[i] & yy = y1[i]
>    d2=(xx-x2)^2+(yy-y2)^2
>    dmch=min(d2,m)
>    IF (option eq 2) or (dmch le dcr2) THEN BEGIN
>     ind1[nmch] = i
>     ind2[nmch] = m
>     nmch = nmch+1
>    ENDIF
>  ENDFOR
>
> My code -->
>
>   lkupx = rebin(indgen(n1),n1,n2)             ;make index lookup
> tables, so as not to
>   lkupy = rebin(transpose(indgen(n2)),n1,n2)  ;worry about confusing
> 1D vs 2D
>   ;use matrix multiplication and dim. juggling to fast compute
> sqrt((x2-x1)^2+(y2-y1)^2)
>   dists =
> sqrt(rebin(x1^2.+y1^2,n1,n2)+rebin(transpose(x2^2.+y2^2),n1, n2)-2*(x1#x2+y1#y2))
>   min_x = min(dists,xmatch,dimension=2)  ;find the minima in both
> directions...
>   min_y = min(dists,ymatch,dimension=1)  ;this is given in 1D indices
>   xm = lkupy[xmatch]  ;convert to 2D indices
>   ym = lkupx[ymatch]
>   ;remove elements w/ distance greater than max_dist, and where the
> two lists don't match
>   nomatch_x = where(ym[xm] ne indgen(n1) or min_x gt max_dist, nmx)
>   if (nmx gt 0) then xm[nomatch_x] = -1
>   nomatch_y = where(xm[ym] ne indgen(n2) or min_y gt max_dist, nmy)
>   if (nmy gt 0) then ym[nomatch_y] = -1
>
> Thanks!!
> --Gray (first time poster)

Gray, have you tried the inbuilt DISTANCE_MEASURE ? I'd be curious to
know if it's any faster.

--Gianguido
Re: For-loop vs. Dimensional Juggling relative performance [message #69738 is a reply to message #69724] Tue, 09 February 2010 07:52 Go to previous messageGo to next message
rogass is currently offline  rogass
Messages: 200
Registered: April 2008
Senior Member
On 9 Feb., 05:26, Gray <grayliketheco...@gmail.com> wrote:
> Hi folks,
>
> I recently wrote my own version of SRCOR from the NASA Astrolib.  Just
> as a reminder, the program takes two lists of 2D coordinates and finds
> matches where the distance is less than some cutoff.  SRCOR uses a for-
> loop to step through the first list, comparing the distance of each
> coordinate-pair from every point in the second list.  My version uses
> matrix multiplication and dimensional juggling to avoid the for-loop.
>
> For n1 = 2143 and n2 = 2115, SRCOR is faster (0.16 seconds to my 0.53
> on my macbook); however, for n1 = 25 and n2 = 26, mine is faster
> (1.8e-4 seconds to 4.2e-4).  Is there any way to predict what kind of
> list sizes will be faster with each method, without making some random
> data and using brute force?
>
> The relevant code is:
>
> SRCOR (dcr2 is the cutoff, option eq 2 ignores the cutoff) -->
>
>  FOR i=0L,n1-1 DO BEGIN
>    xx = x1[i] & yy = y1[i]
>    d2=(xx-x2)^2+(yy-y2)^2
>    dmch=min(d2,m)
>    IF (option eq 2) or (dmch le dcr2) THEN BEGIN
>     ind1[nmch] = i
>     ind2[nmch] = m
>     nmch = nmch+1
>    ENDIF
>  ENDFOR
>
> My code -->
>
>   lkupx = rebin(indgen(n1),n1,n2)             ;make index lookup
> tables, so as not to
>   lkupy = rebin(transpose(indgen(n2)),n1,n2)  ;worry about confusing
> 1D vs 2D
>   ;use matrix multiplication and dim. juggling to fast compute
> sqrt((x2-x1)^2+(y2-y1)^2)
>   dists =
> sqrt(rebin(x1^2.+y1^2,n1,n2)+rebin(transpose(x2^2.+y2^2),n1, n2)-2*(x1#x2+y1 #y2))
>   min_x = min(dists,xmatch,dimension=2)  ;find the minima in both
> directions...
>   min_y = min(dists,ymatch,dimension=1)  ;this is given in 1D indices
>   xm = lkupy[xmatch]  ;convert to 2D indices
>   ym = lkupx[ymatch]
>   ;remove elements w/ distance greater than max_dist, and where the
> two lists don't match
>   nomatch_x = where(ym[xm] ne indgen(n1) or min_x gt max_dist, nmx)
>   if (nmx gt 0) then xm[nomatch_x] = -1
>   nomatch_y = where(xm[ym] ne indgen(n2) or min_y gt max_dist, nmy)
>   if (nmy gt 0) then ym[nomatch_y] = -1
>
> Thanks!!
> --Gray (first time poster)

Hi Gray,
there is some potential to optimise your code:
a) use the SAMPLE keyword within rebin
b) generate one big index and use it again like:
bigind = lindgen(n1>n2,n1>n2) mod (n1>n2)
lkupx=bigind[0:n1-1,0:n2-1]
lkupy=transpose(bigind[0:n2-1,0:n1-1])
nomatch_x = where(ym[xm] ne bigind[0:n1-1] or min_x gt max_dist, nmx)
nomatch_y = where(xm[ym] ne bigind[0:n2-1] or min_y gt max_dist, nmy)
c) just compute x1^2 by using x1*x1 etc. ->its faster because exp
won't be internally used

Nevertheless, your approach might be ever faster for small matrices
because it hasn't any loop overhead, which may not relevant for large
matrices.

Cheers

CR
Re: For-loop vs. Dimensional Juggling relative performance [message #69743 is a reply to message #69738] Mon, 08 February 2010 22:28 Go to previous messageGo to next message
Chris[6] is currently offline  Chris[6]
Messages: 84
Registered: July 2008
Member
On Feb 8, 6:26 pm, Gray <grayliketheco...@gmail.com> wrote:
> Hi folks,
>
> I recently wrote my own version of SRCOR from the NASA Astrolib.  Just
> as a reminder, the program takes two lists of 2D coordinates and finds
> matches where the distance is less than some cutoff.  SRCOR uses a for-
> loop to step through the first list, comparing the distance of each
> coordinate-pair from every point in the second list.  My version uses
> matrix multiplication and dimensional juggling to avoid the for-loop.
>
> For n1 = 2143 and n2 = 2115, SRCOR is faster (0.16 seconds to my 0.53
> on my macbook); however, for n1 = 25 and n2 = 26, mine is faster
> (1.8e-4 seconds to 4.2e-4).  Is there any way to predict what kind of
> list sizes will be faster with each method, without making some random
> data and using brute force?
>
> The relevant code is:
>
> SRCOR (dcr2 is the cutoff, option eq 2 ignores the cutoff) -->
>
>  FOR i=0L,n1-1 DO BEGIN
>    xx = x1[i] & yy = y1[i]
>    d2=(xx-x2)^2+(yy-y2)^2
>    dmch=min(d2,m)
>    IF (option eq 2) or (dmch le dcr2) THEN BEGIN
>     ind1[nmch] = i
>     ind2[nmch] = m
>     nmch = nmch+1
>    ENDIF
>  ENDFOR
>
> My code -->
>
>   lkupx = rebin(indgen(n1),n1,n2)             ;make index lookup
> tables, so as not to
>   lkupy = rebin(transpose(indgen(n2)),n1,n2)  ;worry about confusing
> 1D vs 2D
>   ;use matrix multiplication and dim. juggling to fast compute
> sqrt((x2-x1)^2+(y2-y1)^2)
>   dists =
> sqrt(rebin(x1^2.+y1^2,n1,n2)+rebin(transpose(x2^2.+y2^2),n1, n2)-2*(x1#x2+y1#y2))
>   min_x = min(dists,xmatch,dimension=2)  ;find the minima in both
> directions...
>   min_y = min(dists,ymatch,dimension=1)  ;this is given in 1D indices
>   xm = lkupy[xmatch]  ;convert to 2D indices
>   ym = lkupx[ymatch]
>   ;remove elements w/ distance greater than max_dist, and where the
> two lists don't match
>   nomatch_x = where(ym[xm] ne indgen(n1) or min_x gt max_dist, nmx)
>   if (nmx gt 0) then xm[nomatch_x] = -1
>   nomatch_y = where(xm[ym] ne indgen(n2) or min_y gt max_dist, nmy)
>   if (nmy gt 0) then ym[nomatch_y] = -1
>
> Thanks!!
> --Gray (first time poster)

There's no easy way to figure this out (and it will vary from machine
to machine). You would have to develop some sort of model for
execution time, which would look something like

time = A * lines_of_code_to_execute + B * number_of_math_operations +
f(total_memory_creation_needed)

IDL's speed penalty comes from the fact that A is largeish
(quasi-)constant, since IDL interprets and runs each line individually
(including every iteration in a loop). B is some constant which
depends on the speed of your processor, and f is some function that
models how efficient your operating system is at allocating memory for
your big arrays. A, B, and f are all machine dependent, and would have
to be determined empirically.

Of course, the most efficient approach of all is to realize that the
time difference between the two methods is .5 seconds, and that it's
much faster to just choose one method and run with it :)

chris
Re: For-loop vs. Dimensional Juggling relative performance [message #69814 is a reply to message #69724] Wed, 10 February 2010 19:51 Go to previous message
Jeremy Bailin is currently offline  Jeremy Bailin
Messages: 618
Registered: April 2008
Senior Member
On Feb 9, 9:54 pm, Gianguido Cianci <gianguido.cia...@gmail.com>
wrote:
> On Feb 8, 10:26 pm, Gray <grayliketheco...@gmail.com> wrote:
>
>
>
>
>
>> Hi folks,
>
>> I recently wrote my own version of SRCOR from the NASA Astrolib.  Just
>> as a reminder, the program takes two lists of 2D coordinates and finds
>> matches where the distance is less than some cutoff.  SRCOR uses a for-
>> loop to step through the first list, comparing the distance of each
>> coordinate-pair from every point in the second list.  My version uses
>> matrix multiplication and dimensional juggling to avoid the for-loop.
>
>> For n1 = 2143 and n2 = 2115, SRCOR is faster (0.16 seconds to my 0.53
>> on my macbook); however, for n1 = 25 and n2 = 26, mine is faster
>> (1.8e-4 seconds to 4.2e-4).  Is there any way to predict what kind of
>> list sizes will be faster with each method, without making some random
>> data and using brute force?
>
>> The relevant code is:
>
>> SRCOR (dcr2 is the cutoff, option eq 2 ignores the cutoff) -->
>
>>  FOR i=0L,n1-1 DO BEGIN
>>    xx = x1[i] & yy = y1[i]
>>    d2=(xx-x2)^2+(yy-y2)^2
>>    dmch=min(d2,m)
>>    IF (option eq 2) or (dmch le dcr2) THEN BEGIN
>>     ind1[nmch] = i
>>     ind2[nmch] = m
>>     nmch = nmch+1
>>    ENDIF
>>  ENDFOR
>
>> My code -->
>
>>   lkupx = rebin(indgen(n1),n1,n2)             ;make index lookup
>> tables, so as not to
>>   lkupy = rebin(transpose(indgen(n2)),n1,n2)  ;worry about confusing
>> 1D vs 2D
>>   ;use matrix multiplication and dim. juggling to fast compute
>> sqrt((x2-x1)^2+(y2-y1)^2)
>>   dists =
>> sqrt(rebin(x1^2.+y1^2,n1,n2)+rebin(transpose(x2^2.+y2^2),n1, n2)-2*(x1#x2+y1 #y2))
>>   min_x = min(dists,xmatch,dimension=2)  ;find the minima in both
>> directions...
>>   min_y = min(dists,ymatch,dimension=1)  ;this is given in 1D indices
>>   xm = lkupy[xmatch]  ;convert to 2D indices
>>   ym = lkupx[ymatch]
>>   ;remove elements w/ distance greater than max_dist, and where the
>> two lists don't match
>>   nomatch_x = where(ym[xm] ne indgen(n1) or min_x gt max_dist, nmx)
>>   if (nmx gt 0) then xm[nomatch_x] = -1
>>   nomatch_y = where(xm[ym] ne indgen(n2) or min_y gt max_dist, nmy)
>>   if (nmy gt 0) then ym[nomatch_y] = -1
>
>> Thanks!!
>> --Gray (first time poster)
>
> Gray, have you tried the inbuilt DISTANCE_MEASURE ? I'd be curious to
> know if it's any faster.
>
> --Gianguido

I'd wager that JD's match_2d will knock the socks off both of those...

-Jeremy.
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: Re: dereference with wildcard
Next Topic: How to produce the latex symbol like \overline{X} ?

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 13:49:50 PDT 2025

Total time taken to generate the page: 0.00701 seconds