Re: [perl #22633] [PATCH] convert parrot to continuation passing style
Jonathan Sillito [EMAIL PROTECTED] wrote: Here is another suggestion (I think I mentioned this in another email) we could support a few different types of continuations. The simplest continuation could be just a saved return address (i.e. an opcode_t*). I'm fine with that, if its additionally to the current invoke/ret scheme. One more thing Leo (excuse my ignorance) why is there a stack calling convention in imcc? How does it relate to calling subs via the calling convention? First one sentence from pdd03: Please note that the following conventions are only necessary when exposing subs and methods via the generic parrot routine exposure mechanism. Parrot calling conventions are for subs and methods which ought to be accessible like e.g. library functions. All internal language stuff may use whatever subroutine calling convention that is appropriate. So there are different ways to call a subroutine: - stack calling conventions (callee saves used by BASIC, P6C) - invoke/ret (callee saves used by P6Cs exceptions and rx rules) - above schemes, caller saves IMHO the continuation passing scheme can only be additionally to current schemes. Jonathan Sillito leo
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
Leopold Toetsch [EMAIL PROTECTED] writes: Jonathan Sillito [EMAIL PROTECTED] wrote: Here is another suggestion (I think I mentioned this in another email) we could support a few different types of continuations. The simplest continuation could be just a saved return address (i.e. an opcode_t*). I'm fine with that, if its additionally to the current invoke/ret scheme. One more thing Leo (excuse my ignorance) why is there a stack calling convention in imcc? How does it relate to calling subs via the calling convention? First one sentence from pdd03: Please note that the following conventions are only necessary when exposing subs and methods via the generic parrot routine exposure mechanism. Parrot calling conventions are for subs and methods which ought to be accessible like e.g. library functions. All internal language stuff may use whatever subroutine calling convention that is appropriate. So there are different ways to call a subroutine: - stack calling conventions (callee saves used by BASIC, P6C) The eventual Perl 6 implementation should almost certainly move over to a continuation passing style. -- Piers
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
Jonathan Sillito [EMAIL PROTECTED] wrote: This patch converts parrot to a continuation passing style. You seem to be changing current tests WRT invoke - does invoke still work as it did? Or more specifically: Do imcc tests and perl6 test still pass? I am not satisfied with the time taken to make a call. I did some rough benchmarking and the parrot implementation makes us slower than python 2.2.1. Optimized parrot build? $ perl assemble.pl test.pasm test.pbc ; time ./parrot test.pbc CGP or jit should be a lot faster. Some minor remarks: - the changes s/interp/interpreter/ make it harder the read the real changes - and I don't see any benefit to rename variable names. - you are undoing some PMC_data changes. leo
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
On Tue, Jun 10, 2003 at 04:59:50PM -0700, Robert Spier wrote: mistral-jerome:/tmp time python test.py python test.py 2,59s user 0,00s system 100% cpu 2,582 total mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 0,14s user 0,00s system 106% cpu 0,131 total mistral-jerome:/tmp cat test.ml let foo () = () in for i = 1 to 100 do foo () done That is impressive. I don't know Ocaml but do you think there is an optimization being done since foo takes no args, returns not values and has an empty body? This also isn't a fair comparison. Here are the results when doing ten times more iterations : mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 1,30s user 0,00s system 101% cpu 1,279 total mistral-jerome:/tmp time python -O test.py python -O test.py 22,59s user 0,00s system 98% cpu 23,032 total python is compiling test.py to bytecode during the 'time' call. ocaml is explicitly compiling _to a raw executable_ (and optimizing at three different levels) outside the call. There's no startup overhead for the binary. The startup overhead seems to be rather low. Precompiled Python code : mistral-jerome:/tmp python -O -c \ import sys,py_compile;py_compile.compile(sys.argv[1],sys.argv[2]) \ test.py test.pyc mistral-jerome:/tmp time python test.pyc python test.pyc 22,93s user 0,00s system 100% cpu 22,926 total On-the-fly compilation of the ocaml code : mistral-jerome:/tmp time ocaml test.ml ocaml test.ml 1,33s user 0,01s system 100% cpu 1,336 total Also, (in general) for this kind of test you really need to run each a lot of times and average. There's too many things going on on a typical system that could tweak things. I ran the tests several times, and always got similar results. -- Jerome
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
On Tue, Jun 10, 2003 at 04:00:07PM -0700, Jonathan Sillito wrote: -Original Message- From: Jerome Vouillon [mailto:[EMAIL PROTECTED] The python interpreter seems rather slow. I get these numbers with the Ocaml bytecode interpreter. mistral-jerome:/tmp time python test.py python test.py 2,59s user 0,00s system 100% cpu 2,582 total mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 0,14s user 0,00s system 106% cpu 0,131 total mistral-jerome:/tmp cat test.ml let foo () = () in for i = 1 to 100 do foo () done That is impressive. I don't know Ocaml but do you think there is an optimization being done since foo takes no args, returns not values and has an empty body? No, the bytecode compiler is not performing any optimization in this case. Here is the bytecode produced (the Ocaml virtual machine has an accumulator and a stack). -- Jerome 0 BRANCH 5 Jump to offset 5 (skip the function body). Function foo : 2 CONST0Store 0 in the accumulator (this is the function result). 3 RETURN 1 Pop one element (the function argument). and return. 5 CLOSURE 0, 2 Build the foo function closure (empty environment, code at offset 2). Initialisation of the loop : 8 PUSHCONST1Push the closure on the stack. and store 1 (the loop counter) in the accumulator. 9 PUSHCONSTINT 1000 Push the value of the accumulator. and store 1000 in the accumulator. 11 PUSH Push the value of the accumulator. 12 BRANCH 23 Jump to offset 23. The loop : 14 CHECK_SIGNALS Check whether there is any pending signal (Control-C, for instance) 15 CONST0Store 0 in the accumulator (the function parameter). 16 PUSHACC3 Push the value of the accumulator and access the 4th element of the stack (the function closure). 17 APPLY1Apply the function to its arguments. 18 ACC1 Store the 2nd element of the stack (the loop counter) in the accumulator. 19 OFFSETINT 1 Increment the loop counter. 21 ASSIGN 1 Store the value of the loop counter back in the stack. 23 ACC0 Store the content of the top of the stack (1000) in the accumulator. 24 PUSHACC2 Push the value of the accumulator and store the 3rd element of the stack (the loop counter) in the accumulator. 25 LEINT Compare the accumulator and the top of the stack. The top of the stack is popped and the result is stored in the accumulator. 26 BRANCHIF 14 If the result is true, then jump to offset 14. Clean-up after the loop : 28 CONST0Put 0 in the accumulator (return value of the loop) 29 POP 3 Pop all three elements of the stack
RE: [perl #22633] [PATCH] convert parrot to continuation passing style
-Original Message- From: Leopold Toetsch [mailto:[EMAIL PROTECTED] Jonathan Sillito [EMAIL PROTECTED] wrote: This patch converts parrot to a continuation passing style. You seem to be changing current tests WRT invoke - does invoke still work as it did? Or more specifically: Do imcc tests and perl6 test still pass? Not quite. In the case of sub.pmc the 'next' argument to the invoke vtable function is ignored, instead the continuation to return to is expected to be in P1. All of what used to be just plain 'invoke' now should be 'invokecc' -- this will do the extra setup. So in the normal cases we should use: invokecc # rather than invoke invoke P1# rather than ret All imcc tests pass if the attached tiny patch is applied. Perl6 on the other hand I have never looked at, but I can do that next I guess ... Oh, one other difference is that 'invoke Px' will now put the sub from Px into P0, since this is where the callee will expect it to be. Or is this form of the op intended for something else? I am not satisfied with the time taken to make a call. I did some rough benchmarking and the parrot implementation makes us slower than python 2.2.1. Optimized parrot build? $ perl assemble.pl test.pasm test.pbc ; time ./parrot test.pbc CGP or jit should be a lot faster. Adding --jit does not seem to make a difference. Am I missing somthing? Some minor remarks: - the changes s/interp/interpreter/ make it harder the read the real changes - and I don't see any benefit to rename variable names. This was for consistency since everywhere else 'interpreter' seems to be used. - you are undoing some PMC_data changes. Doh! -- Jonathan Sillito imcc.patch Description: Binary data
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
On Wed, 11 Jun 2003, Leopold Toetsch wrote: Jonathan Sillito wrote: Why not just leave the old behaviour? IMHO[1]: - Make a new class based on Continuations - invokecc and such are based on it [snip] [1] I don't know too much about all the HL stuff. But anyway, some languages might be quite fine with the current implementation (which seems to be more lightweight, when it just comes to calling a plain subroutine) Have a look at P6Cs usage for exceptions and in regexen code. I know, its not final, but its a working implementation. Some less fancy HL might be just fine with the way how its working currently. Or I'm totally wrong here ;-) Here is another suggestion (I think I mentioned this in another email) we could support a few different types of continuations. The simplest continuation could be just a saved return address (i.e. an opcode_t*). This would be roughly as lightweight as the current implementation, I think. What do you think? I am thinking it would be easier to have one calling convention then callees know what to expect. invokecc .LiteContinuation # or something ... One more thing Leo (excuse my ignorance) why is there a stack calling convention in imcc? How does it relate to calling subs via the calling convention? -- Jonathan Sillito
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
Jonathan Sillito writes: Here is another suggestion (I think I mentioned this in another email) we could support a few different types of continuations. The simplest continuation could be just a saved return address (i.e. an opcode_t*). This would be roughly as lightweight as the current implementation, I think. What do you think? I am thinking it would be easier to have one calling convention then callees know what to expect. invokecc .LiteContinuation # or something ... I like the idea. One big thing that was discussed over on p6l is that we want to make good coding style not incur a big performance penalty, like may other languages do. Considering the common definition of good coding style, this means sub calls have to be as cheap as possible. One thing that worries me about the idea is whether it defeats the benefits of a continuation passing style. You can't bottle up a LiteContinuation which only has the return address saved and store it for later. But then again, you can easily promote it if you need to, by making a full-blown continuation that just returns to that spot. I think with this style, though, that it's silly to use the register stacks for sub calls... shouldn't those be stored in the continuation instead? I don't know how this would measure up performance-wise. Anybody? Luke
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
On Tue, Jun 10, 2003 at 06:07:31PM +, Jonathan Sillito wrote: I am not satisfied with the time taken to make a call. I did some rough benchmarking and the parrot implementation makes us slower than python 2.2.1. The most expensive part of our call is the saveall/restoreall that wraps the invokecc. In some cases the caller can be more selective about what is saved, if no saveall/restoreall are used parrot calls are faster than python's. The PASM and python code I used to benchmark along with the times are below. [...] The python interpreter seems rather slow. I get these numbers with the Ocaml bytecode interpreter. mistral-jerome:/tmp time python test.py python test.py 2,59s user 0,00s system 100% cpu 2,582 total mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 0,14s user 0,00s system 106% cpu 0,131 total mistral-jerome:/tmp cat test.ml let foo () = () in for i = 1 to 100 do foo () done -- Jerome
RE: [perl #22633] [PATCH] convert parrot to continuation passing style
-Original Message- From: Jerome Vouillon [mailto:[EMAIL PROTECTED] The python interpreter seems rather slow. I get these numbers with the Ocaml bytecode interpreter. mistral-jerome:/tmp time python test.py python test.py 2,59s user 0,00s system 100% cpu 2,582 total mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 0,14s user 0,00s system 106% cpu 0,131 total mistral-jerome:/tmp cat test.ml let foo () = () in for i = 1 to 100 do foo () done That is impressive. I don't know Ocaml but do you think there is an optimization being done since foo takes no args, returns not values and has an empty body? Also I should have mentioned that python spends between one third and one half of its time executing the loop instructions (test and increment). Parrot is much faster at this of course. Parrot sub and method calls can be made faster or slower depending on how much of the context needs to be saved. I can imagine several types of continuations that differ on how much context they save and restore: a. only an opcode ptr to jump to b. opcode and the stacks c. opcode, stacks and half of the registers d. opcode, stacks and all of the registers The patch I sent supports two types: type b (in continuation.pmc) and type d (in completecontext.pmc). Also in this patch is the option to not create a new continuation --as in a tail call-- which of course makes it very fast. -- Jonathan Sillito
Re: [perl #22633] [PATCH] convert parrot to continuation passing style
mistral-jerome:/tmp time python test.py python test.py 2,59s user 0,00s system 100% cpu 2,582 total mistral-jerome:/tmp ocamlc -o tst test.ml; time ./tst ./tst 0,14s user 0,00s system 106% cpu 0,131 total mistral-jerome:/tmp cat test.ml let foo () = () in for i = 1 to 100 do foo () done That is impressive. I don't know Ocaml but do you think there is an optimization being done since foo takes no args, returns not values and has an empty body? This also isn't a fair comparison. python is compiling test.py to bytecode during the 'time' call. ocaml is explicitly compiling _to a raw executable_ (and optimizing at three different levels) outside the call. There's no startup overhead for the binary. Also, (in general) for this kind of test you really need to run each a lot of times and average. There's too many things going on on a typical system that could tweak things. -R