Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: "Pierre-Evariste Dagand" <pedagand@gmail.com>
To: "Zheng Li" <li@pps.jussieu.fr>, caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Re: "Ref" and copy of functions
Date: Fri, 14 Dec 2007 15:54:55 +0100	[thread overview]
Message-ID: <6cb897b30712140654v26a0ef96we6007c868d3d1829@mail.gmail.com> (raw)
In-Reply-To: <87d4t9k0uy.fsf@pps.jussieu.fr>

[-- Attachment #1: Type: text/plain, Size: 5925 bytes --]

Hi,

> At least on this
> particular example, you can use the following encoding (I
> deliberately use rectypes here, but you can always use extra
> variant instead)
>
> (...)
>
> Since it doesn't use mutable variable, it's free to make copy.

Yes, that's a CPS-way of doing things. I am aware of it and my first
implementation was in this style.

The reasons why I decided to switch to Ref were that :
  1/ The implementation is much more "intuitive" (I don't have a CPS
pre-processor in my brain)
  2/ I thought I could get rid of my hack (Marshal/UnMarshal) easily
  3/ I used to think that I will be faster

Point 1 is not a problem, Santa Claus might bring me this CPS
pre-processor in a few days.

Point 2 seems to be wrong : being fast is nice but if it's for hitting
the wall, well... one should slow down. And for the moment, I haven't
found a clean solution and I'm not sure whether my hack is safe or
not.

So, remains point 3. That's why I have carried out an experience on my
initial Ref implementation, your Rectypes implementation and a CPS
implementation without rectypes (because rectypes frighten me).

%%%%%%%%%%%%%%%%%%%

----------------------------
Ref implementation :
----------------------------

type ('a,'b) arrow = Arrow of ( 'a -> 'b )
let arr f = Arrow (  f )
let (>>>) (Arrow f) (Arrow g) =Arrow ( fun  c -> g  ( f  c ) )
let loop init (Arrow f) =
  let state = ref init in
    Arrow ( fun c ->
                   let new_state , output = f ( !state , c ) in
                     state := new_state;
                     output
              )
let run (Arrow f) input =
  f  input

-----------------------------------
Rectypes implementation :
------------------------------------

let rec arr f x = f x, arr f

let rec (>>>) f g x =
  let rf,nf = f x in let rg,ng = g rf in
 rg, nf >>> ng

let rec run f x ?(i=0) max_inc =
  if i = max_inc then
    x
  else
    let _,n = f x in
      run n x ~i:(i+1) max_inc

--------------------------------------
Variant CPS implementation :
--------------------------------------

type ('a,'b) arrow = Arrow of ( 'a -> 'b * ('a,'b) arrow )

let rec arr f = Arrow ( fun x -> f x , arr f );;

let rec (>>>) (Arrow f) (Arrow g) =
  Arrow (
    fun x ->
      let rf,nf = f x in
      let rg,ng = g rf in
        rg , nf >>> ng
  )

let loop init f  =
  let rec loop_aux c (Arrow f) =
    Arrow (
      fun x->
        let ((c', r), n) = f (c,x) in
          r , loop_aux c' n
    )
  in
    loop_aux init f

let rec run (Arrow f) x ?(i=0) max_inc =
  if i = max_inc then
    x
  else
    let _,n = f x in
      run n x ~i:(i+1) max_inc


%%%%%%%%%%%%%%%%%%%%%

Then I wrote a small test :

%%%%%%%%%%%%%%%%%%%%%

let pair_to_simple (x,y) = x
let arr_pair_to_simple () = arr pair_to_simple
let simple_to_pair x = (x,x)
let arr_simple_to_pair () = arr simple_to_pair
let arr_incr = arr ( fun ( c , x ) -> c + 1 , c + x )
let arr_counter1 = loop 1 arr_incr
let arr_incr1 = (arr_pair_to_simple ()) >>> arr_counter1 >>>
(arr_simple_to_pair ())
let arr_counter2 = loop 2 arr_incr1
let arr_incr2 = (arr_pair_to_simple ()) >>> arr_counter2 >>>
(arr_simple_to_pair ())
let arr_counter3 = loop 3 arr_incr2
let arr_incr3 = (arr_pair_to_simple ()) >>> arr_counter3 >>>
(arr_simple_to_pair ())
let arr_counter4 = loop 4 arr_incr3
let arr_incr4 = (arr_pair_to_simple ()) >>> arr_counter4 >>>
(arr_simple_to_pair ())
let arr_counter5 = loop 5 arr_incr4
let arr_incr5 = (arr_pair_to_simple ()) >>> arr_counter5 >>>
(arr_simple_to_pair ())
let arr_counter6 = loop 6 arr_incr5
let arr_incr6 = (arr_pair_to_simple ()) >>> arr_counter6 >>>
(arr_simple_to_pair ())
let arr_counter7 = loop 7 arr_incr6
let arr_incr7 = (arr_pair_to_simple ()) >>> arr_counter7 >>>
(arr_simple_to_pair ())
let arr_counter8 = loop 8 arr_incr7
let arr_incr8 = (arr_pair_to_simple ()) >>> arr_counter8 >>>
(arr_simple_to_pair ())
let arr_counter9 = loop 9 arr_incr8
let arr_incr9 = (arr_pair_to_simple ()) >>> arr_counter9 >>>
(arr_simple_to_pair ())
let arr_counter10 = loop 10 arr_incr9
let arr_incr10 = (arr_pair_to_simple ()) >>> arr_counter10 >>>
(arr_simple_to_pair ())
let arr_counter11 = loop 11 arr_incr10
let arr_incr11 = (arr_pair_to_simple ()) >>> arr_counter11 >>>
(arr_simple_to_pair ())
let arr_counter12 = loop 12 arr_incr11
let arr_incr12 = (arr_pair_to_simple ()) >>> arr_counter12 >>>
(arr_simple_to_pair ())
let arr_my_arrow () = ( arr_simple_to_pair () ) >>> arr_incr12

%%%%%%%%%%%%%%%%%%%%%%%%

Finally, I measured the processing time with :

%%%%%%%%%%%%%%%%%%%%%%%%

-------------
For Ref
-------------

let _ =
  let ntest =  100000 in
  let start_time = Unix.gettimeofday () in
  let arr_my_arrow = arr_my_arrow () in
    for i=0 to ntest-1 do
      let _ = run arr_my_arrow 2 in
        ()
    done;
    let end_time = Unix.gettimeofday () in
    let time = ( end_time -. start_time ) /. (float_of_int ntest) *.
1000000.0 in
      Printf.printf "Mean processing time : %f microseconds\n" time;

--------------------
For CPS (both)
--------------------

let _ =
  let ntest = 100000 in
  let arr_my_arrow = arr_my_arrow () in
  let start_time = Unix.gettimeofday () in
  let _ = run arr_my_arrow 2 ntest in
    ();
    let end_time = Unix.gettimeofday () in
    let time = ( end_time -. start_time ) /. (float_of_int ntest) *.
1000000.0 in
      Printf.printf "Mean processing time : %f microseconds\n" time;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%

And the results are ...
  1/ Ref : 0.75 microseconds
  2/ Variant CPS : 2.69 microseconds
  3/ Rectypes : 2.80 microseconds
[ compiled with ocamlopt.opt, with -rectypes for 3/ ]

It's about 4 times longer and, against a C++ code, I fear that I can't
afford it.

> It looks like "arrow" is for some kind of flow-like
> programming, then you may also take a look at SDFlow [1].

Yes, it does. For more info : http://www.haskell.org/arrows/

I will take a look at SDFlow, thanks for the hint.

> HTH.

Thanks,

-- 
Pierre-Evariste DAGAND

[-- Attachment #2: measure_ref.ml --]
[-- Type: application/octet-stream, Size: 2495 bytes --]

type ('a,'b) arrow = Arrow of ( 'a -> 'b )

let arr f = Arrow (  f )

let (>>>) (Arrow f) (Arrow g) =
  Arrow ( 
    fun  c ->
      g  ( f  c )
  )

let loop init (Arrow f) = 
  let state = ref init in
    Arrow (
      fun c ->
	let new_state , output = f ( !state , c ) in
	  state := new_state;
	  output
    )

let run (Arrow f) input =
  f  input



let pair_to_simple (x,y) = x
let arr_pair_to_simple () = arr pair_to_simple

let simple_to_pair x = (x,x)
let arr_simple_to_pair () = arr simple_to_pair

let arr_incr = arr ( fun ( c , x ) -> c + 1 , c + x )

let arr_counter1 = loop 1 arr_incr
let arr_incr1 = (arr_pair_to_simple ()) >>> arr_counter1 >>> (arr_simple_to_pair ())

let arr_counter2 = loop 2 arr_incr1
let arr_incr2 = (arr_pair_to_simple ()) >>> arr_counter2 >>> (arr_simple_to_pair ())

let arr_counter3 = loop 3 arr_incr2
let arr_incr3 = (arr_pair_to_simple ()) >>> arr_counter3 >>> (arr_simple_to_pair ())

let arr_counter4 = loop 4 arr_incr3
let arr_incr4 = (arr_pair_to_simple ()) >>> arr_counter4 >>> (arr_simple_to_pair ())

let arr_counter5 = loop 5 arr_incr4
let arr_incr5 = (arr_pair_to_simple ()) >>> arr_counter5 >>> (arr_simple_to_pair ())

let arr_counter6 = loop 6 arr_incr5
let arr_incr6 = (arr_pair_to_simple ()) >>> arr_counter6 >>> (arr_simple_to_pair ())

let arr_counter7 = loop 7 arr_incr6
let arr_incr7 = (arr_pair_to_simple ()) >>> arr_counter7 >>> (arr_simple_to_pair ())

let arr_counter8 = loop 8 arr_incr7
let arr_incr8 = (arr_pair_to_simple ()) >>> arr_counter8 >>> (arr_simple_to_pair ())

let arr_counter9 = loop 9 arr_incr8
let arr_incr9 = (arr_pair_to_simple ()) >>> arr_counter9 >>> (arr_simple_to_pair ())

let arr_counter10 = loop 10 arr_incr9
let arr_incr10 = (arr_pair_to_simple ()) >>> arr_counter10 >>> (arr_simple_to_pair ())

let arr_counter11 = loop 11 arr_incr10
let arr_incr11 = (arr_pair_to_simple ()) >>> arr_counter11 >>> (arr_simple_to_pair ())

let arr_counter12 = loop 12 arr_incr11
let arr_incr12 = (arr_pair_to_simple ()) >>> arr_counter12 >>> (arr_simple_to_pair ())

let arr_my_arrow () = ( arr_simple_to_pair () ) >>> arr_incr12;;


let _ =
  let ntest =  100000 in
  let start_time = Unix.gettimeofday () in
  let arr_my_arrow = arr_my_arrow () in
    for i=0 to ntest-1 do
      let _ = run arr_my_arrow 2 in
	()
    done;
    let end_time = Unix.gettimeofday () in
    let time = ( end_time -. start_time ) /. (float_of_int ntest) *. 1000000.0 in
      Printf.printf "Mean processing time : %f microseconds\n" time;

[-- Attachment #3: measure_rectypes.ml --]
[-- Type: application/octet-stream, Size: 2434 bytes --]

let rec arr f x = f x, arr f;;

let rec (>>>) f g x =
  let rf,nf = f x in let rg,ng = g rf in
 rg, nf >>> ng;;

let rec loop init f x =
  let ((init', r), n) = f (init,x) in
 r, loop init' n;;

let rec run f x ?(i=0) max_inc = 
  if i = max_inc then
    x
  else
    let _,n = f x in
      run n x ~i:(i+1) max_inc
	

let pair_to_simple (x,y) = x
let arr_pair_to_simple () = arr pair_to_simple

let simple_to_pair x = (x,x)
let arr_simple_to_pair () = arr simple_to_pair

let arr_incr = arr ( fun ( c , x ) -> c + 1 , c + x )

let arr_counter1 = loop 1 arr_incr
let arr_incr1 = (arr_pair_to_simple ()) >>> arr_counter1 >>> (arr_simple_to_pair ())

let arr_counter2 = loop 2 arr_incr1
let arr_incr2 = (arr_pair_to_simple ()) >>> arr_counter2 >>> (arr_simple_to_pair ())

let arr_counter3 = loop 3 arr_incr2
let arr_incr3 = (arr_pair_to_simple ()) >>> arr_counter3 >>> (arr_simple_to_pair ())

let arr_counter4 = loop 4 arr_incr3
let arr_incr4 = (arr_pair_to_simple ()) >>> arr_counter4 >>> (arr_simple_to_pair ())

let arr_counter5 = loop 5 arr_incr4
let arr_incr5 = (arr_pair_to_simple ()) >>> arr_counter5 >>> (arr_simple_to_pair ())

let arr_counter6 = loop 6 arr_incr5
let arr_incr6 = (arr_pair_to_simple ()) >>> arr_counter6 >>> (arr_simple_to_pair ())

let arr_counter7 = loop 7 arr_incr6
let arr_incr7 = (arr_pair_to_simple ()) >>> arr_counter7 >>> (arr_simple_to_pair ())

let arr_counter8 = loop 8 arr_incr7
let arr_incr8 = (arr_pair_to_simple ()) >>> arr_counter8 >>> (arr_simple_to_pair ())

let arr_counter9 = loop 9 arr_incr8
let arr_incr9 = (arr_pair_to_simple ()) >>> arr_counter9 >>> (arr_simple_to_pair ())

let arr_counter10 = loop 10 arr_incr9
let arr_incr10 = (arr_pair_to_simple ()) >>> arr_counter10 >>> (arr_simple_to_pair ())

let arr_counter11 = loop 11 arr_incr10
let arr_incr11 = (arr_pair_to_simple ()) >>> arr_counter11 >>> (arr_simple_to_pair ())

let arr_counter12 = loop 12 arr_incr11
let arr_incr12 = (arr_pair_to_simple ()) >>> arr_counter12 >>> (arr_simple_to_pair ())

let arr_my_arrow () = ( arr_simple_to_pair () ) >>> arr_incr12;;

let _ =
  let ntest =  100000 in
  let arr_my_arrow = arr_my_arrow () in
  let start_time = Unix.gettimeofday () in
  let _ = run arr_my_arrow 2 ntest in
    ();
    let end_time = Unix.gettimeofday () in
    let time = ( end_time -. start_time ) /. (float_of_int ntest) *. 1000000.0 in
      Printf.printf "Mean processing time : %f microseconds\n" time;
      

[-- Attachment #4: measure_pure_cps.ml --]
[-- Type: application/octet-stream, Size: 2651 bytes --]

type ('a,'b) arrow = Arrow of ( 'a -> 'b * ('a,'b) arrow )

let rec arr f = Arrow ( fun x -> f x , arr f );;

let rec (>>>) (Arrow f) (Arrow g) =
  Arrow (
    fun x ->
      let rf,nf = f x in 
      let rg,ng = g rf in
	rg , nf >>> ng 
  )
;;

let loop init f  =
  let rec loop_aux c (Arrow f) =
    Arrow (
      fun x->
	let ((c', r), n) = f (c,x) in
	  r , loop_aux c' n
    )
  in
    loop_aux init f
;;

let rec run (Arrow f) x ?(i=0) max_inc = 
  if i = max_inc then
    x
  else
    let _,n = f x in
      run n x ~i:(i+1) max_inc


let pair_to_simple (x,y) = x
let arr_pair_to_simple () = arr pair_to_simple

let simple_to_pair x = (x,x)
let arr_simple_to_pair () = arr simple_to_pair


let arr_incr = arr ( fun ( c , x ) -> c + 1 , c + x )

let arr_counter1 = loop 1 arr_incr
let arr_incr1 = (arr_pair_to_simple ()) >>> arr_counter1 >>> (arr_simple_to_pair ())

let arr_counter2 = loop 2 arr_incr1
let arr_incr2 = (arr_pair_to_simple ()) >>> arr_counter2 >>> (arr_simple_to_pair ())

let arr_counter3 = loop 3 arr_incr2
let arr_incr3 = (arr_pair_to_simple ()) >>> arr_counter3 >>> (arr_simple_to_pair ())

let arr_counter4 = loop 4 arr_incr3
let arr_incr4 = (arr_pair_to_simple ()) >>> arr_counter4 >>> (arr_simple_to_pair ())

let arr_counter5 = loop 5 arr_incr4
let arr_incr5 = (arr_pair_to_simple ()) >>> arr_counter5 >>> (arr_simple_to_pair ())

let arr_counter6 = loop 6 arr_incr5
let arr_incr6 = (arr_pair_to_simple ()) >>> arr_counter6 >>> (arr_simple_to_pair ())

let arr_counter7 = loop 7 arr_incr6
let arr_incr7 = (arr_pair_to_simple ()) >>> arr_counter7 >>> (arr_simple_to_pair ())

let arr_counter8 = loop 8 arr_incr7
let arr_incr8 = (arr_pair_to_simple ()) >>> arr_counter8 >>> (arr_simple_to_pair ())

let arr_counter9 = loop 9 arr_incr8
let arr_incr9 = (arr_pair_to_simple ()) >>> arr_counter9 >>> (arr_simple_to_pair ())

let arr_counter10 = loop 10 arr_incr9
let arr_incr10 = (arr_pair_to_simple ()) >>> arr_counter10 >>> (arr_simple_to_pair ())

let arr_counter11 = loop 11 arr_incr10
let arr_incr11 = (arr_pair_to_simple ()) >>> arr_counter11 >>> (arr_simple_to_pair ())

let arr_counter12 = loop 12 arr_incr11
let arr_incr12 = (arr_pair_to_simple ()) >>> arr_counter12 >>> (arr_simple_to_pair ())

let arr_my_arrow () = ( arr_simple_to_pair () ) >>> arr_incr12;;


let _ =
  let ntest = 100000 in
  let arr_my_arrow = arr_my_arrow () in
  let start_time = Unix.gettimeofday () in
  let _ = run arr_my_arrow 2 ntest in
    ();
    let end_time = Unix.gettimeofday () in
    let time = ( end_time -. start_time ) /. (float_of_int ntest) *. 1000000.0 in
      Printf.printf "Mean processing time : %f microseconds\n" time;

  parent reply	other threads:[~2007-12-14 14:54 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-13 17:27 Pierre-Evariste Dagand
2007-12-14 10:49 ` Zheng Li
2007-12-14 14:51   ` [Caml-list] " David Teller
2007-12-14 16:19     ` Zheng Li
2007-12-14 14:54   ` Pierre-Evariste Dagand [this message]
2007-12-14 16:12     ` Zheng Li
2007-12-14 16:55       ` [Caml-list] " Pierre-Evariste Dagand
2007-12-14 16:30     ` Loup Vaillant
     [not found]       ` <6cb897b30712140848j52e5628avbf0e3dadcb771f71@mail.gmail.com>
2007-12-14 16:57         ` Pierre-Evariste Dagand
2007-12-16  5:17 ` [Caml-list] " Jacques Garrigue
2007-12-16 16:39   ` Pierre-Evariste Dagand
2007-12-16 18:27     ` Pierre-Evariste Dagand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6cb897b30712140654v26a0ef96we6007c868d3d1829@mail.gmail.com \
    --to=pedagand@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    --cc=li@pps.jussieu.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox