1. Reverse() was: Win32Lib Update

Ralf Nieuwenhuijsen wrote:
> Why not start a thread ? blink
> function reverse_flat (sequence s)
> sequence result
>     result = {}
>     for index = 1 to length(s) do
>         result = prepend(result, s[index])
>     end for
>     return result
> end function

I'll jump in here :>
y'all should know i cannae r'fuse a speed tweak :>


let's try:

func rev_flat(seq data)
seq result
int len, from
   len    = length(data)
   from   = len --i really could reuse len....
   result = repeat(0,len) --BOOM, call alloc *once*
   for toindex = 1 to len do
        result[toindex] = data[from]
        from = from - 1 --and this takes 1 single tick...
   end for
   return result
end func

now, this (should be/is) faster than prepend...
1:im not having to worry about all that alloc,
alloc even more, alloc even more AGAIN... etc...
that prepend/append will do as it grows a new seq...

yes, pre/append DOES alloc a little more... but,
i have seen EU take a realllyyyy hard, long "think"
in my fuzzy logic library on attempting to find a
'truth' while performing image recognition chores...

this is how/why i found this method, and no, i haven't
had time to update all of the fuzzy library to take
advantage of this...

someone once said on the list that repeat() doesn't
work good on large sequence creation, like after a
couple hundred thousand or so.... i never found that...
has anyone???

2: im only swapping pointers :)

and, of course, recursing this would be easy....

func recurseREV(seq data)
seq result
int len, from
object temp
   len    = length(data)
   from   = len
   result = repeat(0,len)
   for toindex = 1 to len do
        temp = data[from]
        if atom(temp) then
             result[toindex] = temp
        else result[toindex] = recurseREV(temp)
        end if
        from = from - 1
   end for
   return result
end func

so... who gonna bncmrk???
:)
ta! --Hawke'

new topic     » topic index » view message » categorize

2. Re: Reverse() was: Win32Lib Update

Hawke suggested:
>now, this (should be/is) faster than prepend...
>1:im not having to worry about all that alloc,
>alloc even more, alloc even more AGAIN... etc...
>that prepend/append will do as it grows a new seq...

As I recall, an append/prepend as only statement in a for-block will be
optimized to one alloc, one pass proccesing.

>yes, pre/append DOES alloc a little more... but,
>i have seen EU take a realllyyyy hard, long "think"
>in my fuzzy logic library on attempting to find a
>'truth' while performing image recognition chores...

You were prolly appending/prepending to an sliced/indexed sequence. All
optimization fails at this point: result, for every append/prepend, it
reallocates a sequence of the new length, copies the old sequence, copies
the new part, frees the old sequence. And yes, this is sloooww indeed.

>someone once said on the list that repeat() doesn't
>work good on large sequence creation, like after a
>couple hundred thousand or so.... i never found that...
>has anyone???

Me neither.

>so... who gonna bncmrk???


Maybe later today.. still working on my new graphical botmatch routines..

Ralf

new topic     » goto parent     » topic index » view message » categorize

3. Re: Reverse() was: Win32Lib Update

Ralf Nieuwenhuijsen wrote:
> Hawke suggested:
> >now, this (should be/is) faster than prepend...
> >1:im not having to worry about all that alloc,
> >alloc even more, alloc even more AGAIN... etc...
> >that prepend/append will do as it grows a new seq...

> As I recall, an append/prepend as only statement in a for-block will be
> optimized to one alloc, one pass proccesing.
errrrr.... i really don't think so....
see irv's benchmarks...
ummmm.... the prepend came in last... :/

i could make mine go even faster, especially for large
iterations of piddly sized sequences (like the one
thrown at it in the benchmark...)
the newer, tweaked just a little more (alot for large
iteration/small sequences) is:
func rev(seq data)
int junk
seq result
   junk = length(data)
   for from = 1 to junk do
        result[from] = data[junk]
        junk = junk - 1
   end for
   return result
end func
i just saved 100000 clock ticks for irv's bnchmrk...
not shabby...
a million length seq? saved 1000000 clock ticks...

the reason this came in second to mine is:
x = length(s)
r = repeat(0,x)
for i = 1 to x do
   r[i] = s[x-i+1]      --right here, you blew 100000 ticks...
end for                 --million length? 1000000 ticks...
return r

> >yes, pre/append DOES alloc a little more... but,
> >i have seen EU take a realllyyyy hard, long "think"
> >in my fuzzy logic library on attempting to find a
> >'truth' while performing image recognition chores...

> You were prolly appending/prepending to an sliced/indexed sequence. All
> optimization fails at this point: result, for every append/prepend, it
> reallocates a sequence of the new length, copies the old sequence, copies
> the new part, frees the old sequence. And yes, this is sloooww indeed.
actually, i was doing nearly exactly what you were...
to wit:
you have a pair of sequences... indicies matching element for element...
you want to know the minimum value at each index and grab that
element...
a={10,20,10,0,10,20}
b={20,20,10,20,0,10}
u have min()
func min (atom a, atom b)
   if a>b then a=b end if
   return a
end func
(its faster than the one by carl for large seq...)

so.... i tried this first... it's what u are suggesting,
a one statment for block...
func one(seq: l1, l2)
seq r r={}
   for i = 1 to length(l1) do
      r = r & min(l1,l2)
   end for
   return r
end func
and.... it's slowwwww...
throw a few 800x600x16.7M images at it... u snore...
(remembering to adjust for each pixel being a length3 seq)
i then did:
func two(seq l1,l2)
int len
seq r
len = length(l1)
r = repeat(0,len)
   for i = 1 to len do
        r[i] = min(l1,l2)
   end for
   return i
end for
and i began clocking decent speeds....
*shrug*...

i wouldn't have offered my observations about this pre/appending
issue had i not watched EU suddenly BOG when i went over about
a 400x400x16.7M image....

i was clocking what i thought were good timings in the fuzzy logic
computations... i tried a 100x100x1 sequence... flew along, had
to do a couple thousand iterations to build up to a second... went
to 200x200x1... roughly doubled time... 300x300x1.. still no worries...
started working on really bigXfew iterations....
1000000x1... clipped along... 100000x10... no worries... etc...
then reversed that... really smallXlots iterations...
10x10000... no prob... 100x1000... zoom...
so i said... lets go truecolor...
100x100x3 was bout 3 times as long as 100x100x1...
took like a second... 200x200x3 was bout 5 (i think...,
these numbers don't need to be accurate, because it was
the relationship of the values that will bear out in a moment)
and 300x300x3 was.. mebbe a minute...
i hit 400x400x3 (or so...) and **WHAM**
i went, got coffee, came back, smoked a cig, came back,
... nada... it took like 15 minutes... just out of nowhere...
shoulda been ...ohhh... maybe 3 minutes *tops*
so i said this won't do... and found the problem to be
appending/prepending... once i started playing the shuffle
pointer game, it smoothed out and its a pretty fast library
as a result of the extensive benchmarking i did on this issue...


hope this helps someone... --Hawke'

new topic     » goto parent     » topic index » view message » categorize

4. Re: Reverse() was: Win32Lib Update

>> As I recall, an append/prepend as only statement in a for-block will be
>> optimized to one alloc, one pass proccesing.
>errrrr.... i really don't think so....
>see irv's benchmarks...
>ummmm.... the prepend came in last... :/

;-(

Robert, said append and prepend were like, really really optimized.
And for-statements as well..

So, Robert (or Junko now it seems blink again, could there be some 'extra'
optimization with statement blocks like for- and while- . Esspecially when
they contain only one statement. (which should be fairly easy to optimize).
But I was also thinking of multiple 'slices'/'indexes' to be looked up only
once, within a statement block. And off couse the "for each item in
my-sequence do" - syntax provides both optimization 'oppertunities' as well
as increased error checking, and more readable code.

Ralf

new topic     » goto parent     » topic index » view message » categorize

5. Re: Reverse() was: Win32Lib Update

My attemp:

function reverse(object data)
    object aux
    integer midway
    if sequence(data) then
        midway = floor(length(data) / 2)
        if midway != (length(data) / 2) then
            for index = 1 to midway do
                aux = reverse(data[index])
                data[index] = reverse(data[(midway*2) - index + 2])
                data[(midway*2) - index + 2] = aux
            end for
            data[midway+1] = reverse(data[midway+1])
        else
            for index = 1 to midway do
                aux = reverse(data[index])
                data[index] = reverse(data[(midway*2) - index + 1])
                data[(midway*2) - index + 1] = aux
            end for
        end if
    end if
    return data
end function

I'm no speed demon, but I belive this routine is fairly fast and most
important... it's generic and flexible.

Regards,
    Daniel   Berstein
    daber at pair.com

new topic     » goto parent     » topic index » view message » categorize

6. Re: Reverse() was: Win32Lib Update

Ad Rienks writes:
> I'm sorry, but I made a mistake. The function reverse() *is*
> in the 'official' release of Win32Lib v0.15a, it was only missing
> from the copy sent with the calc021 program.

Thanks for pointing this out. It was my mistake. It's corrected now.
Since adding a reverse() function to misc.e for 2.1, I have to
remove Cuny's reverse() before running win32lib programs. I
accidentally uploaded calc021 minus his reverse().

This raises a couple of issues:
    1. I should probably not make it an error (just a warning) to override
        a global symbol with a local symbol. The local should
        take precedence within the file it is declared in.
        I'm not sure if I'll do it for this release. It involves changes
        to compile-time symbol lookup, run-time symbol lookup
       (trace and routine_id) as well as the bind.ex program.
       It would alleviate some of the namespace conflicts.

    2. Which reverse() is the fastest? I was planning to add a
         Euphoria-coded reverse() to misc.e. A few weeks ago
         I coded reverse5() below, but it looks like reverse2() (Hawke)
         is the fastest, so I'll use his unless someone comes up
         with something even faster.

-- taken from Irv's last post:
without type_check
include machine.e
tick_rate(100)

sequence before, after
atom start, fini

before = "Now is the time for all good men to come get drunk at the party."

function reverse1(sequence s)  -- Ralf
sequence r
r = {}
for i = 1 to length(s) do
     r = prepend(r,s[i])
end for
return r
end function

function reverse2(sequence data)  -- Hawke' (newer one)
sequence result
integer len
len = length(data)
result = repeat(0,len) --BOOM, call alloc *once*
for toindex = 1 to len do -- initial value of len sets the limit
     result[toindex] = data[len]
     len = len - 1
end for
return result
end function

function reverse3 (sequence s)  -- Irv
atom temp, left, right
left = 1
right = length(s)
while left < right do
     temp = s[left]
     s[left] = s[right]
     s[right] = temp
     left = left + 1
     right = right - 1
end while
return s
end function

function reverse4 (sequence s)  -- Ad Rienks
atom x
sequence r
x = length(s)
r = repeat(0,x)
for i = 1 to x do
     r[i] = s[x-i+1]
end for
return r
end function

function reverse5(sequence s)  -- Rob Craig
    object temp
    integer n

    n = length(s)+1
    for i = 1 to floor((n-1)/2) do
        temp = s[i]
        s[i] = s[n-i]
        s[n-i] = temp
    end for
    return s
end function

function reverse6( sequence s1 )  -- David Cuny
-- reverse a sequence
-- Ex:  reverse( "12345" )
--      --> "54321"
sequence s2

s2 = {}
for i =length(s1) to 1 by -1 do
     s2 = append( s2, s1[i] )
end for
return s2
end function

procedure measure(sequence name)
-- time a routine
    integer id
    id = routine_id(name)
    start = time()
    for i = 1 to 100000 do
         -- not a normal call, but shouldn't make much difference
         after = call_func(id, {before})
    end for
    fini = time()
    printf(1, "%s: %.2f seconds for 100000 iterations\n", {name,
              fini-start})
    puts(1, after)
    puts(1, '\n')
end procedure

measure("reverse1") -- 5.06
measure("reverse2") -- 3.30
measure("reverse3") -- 3.68
measure("reverse4") -- 4.08
measure("reverse5") -- 3.86
measure("reverse6") -- 5.20

Regards,
     Rob Craig
     Rapid Deployment Software
     http://members.aol.com/FilesEu/

new topic     » goto parent     » topic index » view message » categorize

7. Re: Reverse() was: Win32Lib Update

>I'm no speed demon, but I belive this routine is fairly fast and most
>important... it's generic and flexible.


Well.... after Rob's post I realized that it ain't "fairly fast"... ;) At
least
compared to the other 6 routines posted.

But I still like the "idea" of:

1.- Iterate n/2 times
2.- Don't create a new sequence. What if the sequence is very large?
Memory swaping time would be significant?

Regards,
    Daniel   Berstein
    daber at pair.com

new topic     » goto parent     » topic index » view message » categorize

8. Re: Reverse() was: Win32Lib Update

Daniel Berstein wrote:
>But I still like the "idea" of:
>1.- Iterate n/2 times
that has promise... need better implementation that doesn't
require any calculations *within* the loop (which is the other
reason reverse#2 is the fastest: i only do a *single* "inc()"
with the next best doing a subtraction AND an inc() within
the loop, requiring TWICE as many clock ticks.

>2.- Don't create a new sequence.
>What if the sequence is very large?
>Memory swaping time would be significant?
actually, repeat() is extremely fast, likely nothing more than:

function repeat(object what, integer howmuch)
pointertype pntr, where
   pntr = alloc(howmuch + GLOBALVARSEQOVERHEAD)
   where= pntr + GLOBALVARSEQOVERHEAD
   memset(where, what, howmuch)
   --return pointer
   --return where   --dunno which you return...
end function

so the very large sequence issue is not a factor.

we can then address the memory swapping time by simply saying
what was in the comments in my first post of reverse2(), namely:
we are only swapping pointers.  *fast*

okay.....
i thought of another way, that is 'approaching assembly'
and, at this point, i'm rather sure this is bad code...

it's presented as a *concept* or as *pseudocode* and
if someone can actually take this and make it work,
i'd be happy to share credit :)

this may work real well for single dim sequences...
  ie: strings.
it could be *the* speed demon for strings, i think...
can't use memcopy/memset that i can see, as we cannot
"reverse" the order of their element grabbing, so that's out.

at this point, the only reason it "won't work" is that
we aren't returning a *sequence* but a pointer...

but then, what is the *actual* definition of a sequence after all...
likely a *pointer* to a block of data, and that data is either a
byte(s), or a pointer(s) to another block(s) of data at an
element's index for atoms and other sequences occupying that
element, along with a few bytes for overhead describing start
and end memory addresses...

so, how do i retrieve the overhead?
if i had the overhead, we could, in theory, recreate
a "sequence pointer" by prepend/appending the overhead
to the pointer variable in the example below...

if Rob is planning to use the #2 algorithm for reverse,
i would think an examination of this methodology
would be in order first.  I'm not sure anyone but
Rob, with his intimate knowledge of "sequence" as
defined in ex(w).exe, could pull this off.
Pete, of course, might, for PEU, be able to as well...

and i'm not insulting anyone's intelligence with that
last paragraph, nor am i intending to do so, nor am
i intending to ruffle any feathers. please, don't
take what i said wrong...

i would really like to see someone make this algorithm
work, at least for strings, to see it's benchmrk
against the fastest algorithm to date.

code follows.
take care all--Hawké

-----reverse function presented in Rob's Measure() format:
-----Hawké, tweak to reverse2
-----begin pseudocode of non-functional function
function reverse7( sequence data )
object old
integer len
atom pointer
len = length(data)
pointer = alloc(len) -- + GLOB_VAR_SEQ_OVERHEAD??
--if not alloc() then blahblahblah end if
for toindex = 1 to len do
   old = peek( data + len, 1 ) -- +/- GLOB_VAR_SEQ_OVERHEAD??
   poke( pointer + toindex, old )
   len = len - 1
end for
----ummm what do we do about the return???
----return pointer???? NOT! it's not a sequence...
end function
-----------end broken function

new topic     » goto parent     » topic index » view message » categorize

9. Re: Reverse() was: Win32Lib Update

I tweaked mine a bit to eliminate a subtraction.
It now seems to be a tad faster than Hawke's, but they're
close enough that I decided to try various lengths
of sequence.

function reverse5(sequence s)  -- Rob Craig
    object temp
    integer n

    n = length(s)
    for i = 1 to floor(n/2) do
        temp = s[i]
        s[i] = s[n]
        s[n] = temp
        n = n - 1
    end for
    return s
end function

length    reverse2 (Hawke)   reverse5 (Rob)
0                  0.33                         0.25
1                  0.43                         0.25
2                  0.50                         0.48
5                  0.65                         0.60
10                0.84                         0.85
100              5.01                         4.55
1000          62.33                       48.19
10000      830.77                    528.14

Regards,
     Rob Craig
     Rapid Deployment Software
     http://members.aol.com/FilesEu/

new topic     » goto parent     » topic index » view message » categorize

10. Re: Reverse() was: Win32Lib Update

Rob,

Can you test my reverse function out and compare its speed to yours and
hawkey's?

Thanks
Albert

new topic     » goto parent     » topic index » view message » categorize

11. Re: Reverse() was: Win32Lib Update

Albert Brauneis writes:
> Can you test my reverse function out and compare its speed to
> yours and hawkey's?

Your inner loop is:

          back = back & rev[junk]

This is wrong. What if rev[junk] is a sequence?

You should have said:
          back = append(back, rev[junk])
which is the way you originally had it. append() will be
just as fast as &.

Looping with append() will be similar to Cuny's reverse(),
which is one of the slowest.

Timing code is not rocket science. Just use:

     atom t
     t = time()
     for i = 1 to 10000 do
         -- call your routine here
     end for
     ? time() - t

Regards,
     Rob Craig
     Rapid Deployment Software
     http://members.aol.com/FilesEu/

new topic     » goto parent     » topic index » view message » categorize

12. Re: Reverse() was: Win32Lib Update

>>2.- Don't create a new sequence.
>>What if the sequence is very large?
>>Memory swaping time would be significant?
>actually, repeat() is extremely fast, likely nothing more than:
>
>function repeat(object what, integer howmuch)
>pointertype pntr, where
>   pntr = alloc(howmuch + GLOBALVARSEQOVERHEAD)
>   where= pntr + GLOBALVARSEQOVERHEAD
>   memset(where, what, howmuch)
>   --return pointer
>   --return where   --dunno which you return...
>end function
>
>so the very large sequence issue is not a factor.


That's not the point. The point is that if the sequence is very large, we
can get off physical memory. Disk read/write is far slower than
RAM. In such a situation would it be faster to use a slower algorithm,
but that doesn't create a new sequence?

Regards,
    Daniel   Berstein
    daber at pair.com

new topic     » goto parent     » topic index » view message » categorize

13. Re: Reverse() was: Win32Lib Update

>I tweaked mine a bit to eliminate a subtraction.
>It now seems to be a tad faster than Hawke's, but they're
>close enough that I decided to try various lengths
>of sequence.


>length    reverse2 (Hawke)   reverse5 (Rob)
>0                  0.33                         0.25
>1                  0.43                         0.25
>2                  0.50                         0.48
>5                  0.65                         0.60
>10                0.84                         0.85
>100              5.01                         4.55
>1000          62.33                       48.19
>10000      830.77                    528.14


Mmmm... my machine says other thing. I also created another reverse
routine, it's between your's and Hawke'. I suppose it's slower than
Hawke''s routine because substraction is slower than addtion
(complement-2 computed, then addition?). Does having a hard
typed constant as end value of a loop increase performance?

function reverse9(sequence s)
    integer n, m, q, k
    sequence r
    n = length(s)
    m = floor(n/2)
    r = repeat(0,n)
    q = n+1
    for i = m to n do
        k = q-i
        r[k] = s[i]
        r[i] = s[k]
    end for
    return r
end function

Using the benchmark posted earlier (64 charcters sequence with
100000 iterations):

reverse2        reverse5        reverse9
(Hawke)        (Rob)              (Daniel)

1.21 sec.        1.69 sec.        1.39 sec.

The fastest (read: unbeatable) reverse function will be one that iterates
n/2 times, and do not make any substraccion inside the loop.

My machine is a Celeron 300, with *no* cache... I guess that gives pure
algorithmic results?

I'm having fun with this thread! Can we expand it to a recursive version
too...

Regards,
    Daniel   Berstein
    daber at pair.com

new topic     » goto parent     » topic index » view message » categorize

14. Re: Reverse() was: Win32Lib Update

>This raises a couple of issues:
>    1. I should probably not make it an error (just a warning) to override
>        a global symbol with a local symbol. The local should
>        take precedence within the file it is declared in.
>        I'm not sure if I'll do it for this release. It involves changes
>        to compile-time symbol lookup, run-time symbol lookup
>       (trace and routine_id) as well as the bind.ex program.
>       It would alleviate some of the namespace conflicts.

Ive mentioned this before, a warning might be in place, but you should
always be able to overwrite a global identifer with a local identifer. I
only think you should see a warning when you overwrite a global identifer.

>    2. Which reverse() is the fastest? I was planning to add a
>         Euphoria-coded reverse() to misc.e. A few weeks ago
>         I coded reverse5() below, but it looks like reverse2() (Hawke)
>         is the fastest, so I'll use his unless someone comes up
>         with something even faster.


Good, it sounds like we're going to see some general purpose routines, and
maybe containing a boolean type. Ive had many conflicts with them that I
decided to add them to the beginning of every file *locally* .. if they
would in an standard Euphoria file, one could trust the convention.

Its just:

global constant
 TRUE = 1,
 FALSE = 0,
 NONE = -1

global type boolean (object x)
    if integer (x) then
        return x > -2 and x < 2
    else
        return FALSE
    end if
end type


The none is just a flag value. And could be used with result of find () or
any of the input routines.

Ralf

new topic     » goto parent     » topic index » view message » categorize

15. Re: Reverse() was: Win32Lib Update

Daniel wrote:

>I'm having fun with this thread! Can we expand it to a recursive version=

>too...

>Regards,
>    Daniel   Berstein

So Ralf, it was a good idea of you (as many of your ideas are, btw) --
Slime, slime blink
Ad

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu