Re: stackless implementation (was Re: New stackless proposal)

Christian Tismer <[email protected]>
Newsgroups gmane.comp.lang.prothon.user
Message-ID <[email protected]>
Mark Hahn wrote:

>>>Does your assembly only work on X86 machines?  I may ask to steal your
>>>assembly code.
>>
>>Sure. Here an excerpt of slp_platformselect.h .

...

> Wow!  I'm impressed.  I thought I'd only be stealing your ideas.  It would
> be great if I could steal your code for Prothon.  Will you let it go under a
> Python type license?

Stackless is under Python license, of course.

> This will let me have C extenstions in all types of threads.  If there is
> anything we can do in Prothon to make your code faster or easier let me
> know.

Well, we have to talk about this.
You just discovered Stackless 2.0, which was hardware
switching, only.

I will show you how I do it.
The trick is to intercept C extension callbacks by counting
something like nested interpreter invocations. I have a variable
named "nesting_level" in every tasklet.
Tasklets at nesting_level 0 are "innocent". They have a nonexistant,
or trivial C stack, that is, even if they might have one which is
not empty, the C stack can be discarded. These tasklets are in a shape
that always allows you to restart them from "toplevel".

Then there are those with a non-zero nesting_level. They contain
C state that has to be restored, at some time, under all circumstances.
I have special treatment for these. For instance, I don't allow any
tasklet with such a C state to simply go away. It *must* be finalized
by a TaskletExit exception, to make sure that it had the chance to
und any C state it had changed.

I even do this cross-real-thread. My code can kill any tasklet, in
this or in any other real thread. This took me months, but it works.

> So, does it just copy the C stack into the Object stack space and pop the C
> stack and vice versa?

Yes, it has a concept of an "initial stub" piece of C stack, which
is squirreled away at every entry into an initial interpreter.
This is also the default initial stack for "innocent" tasklets,
which don't really need C state at all.

My implementation is a bit sub-optimal here, and this is where
you might be interested in the Greenlets, again. Armin made this
solution uch more general. I'm not too much after it, because
my major target is soft-switching (not involving asm hacks).
But finally, he has the most general and efficient solution possible,
although it isn't implemented completely, yet.

Armin is btw. using the same set of assembly include files as
Stackless does. He just provides some different supporting
macroes.
The assembly includes appear to be somewhat of a real optimum;
they have typically about five lines of assembly. It is then
the art to use these in the best way. I am happy to help here.

On the "initial stub" idea: The idea is to use a fixed location
in the stack when the stack is touched first by tasklets.
All further ahrd-switching uses this base address.
Armin proved that this is not necessary, and every hard-switched
tasklet can maintain its own subset of C stack that it controls.
I'm going to implement this for Stackless in the near future.
At the moment, I am more concerned with efficient soft-switching,
because this is almost always more efficient.

Well, we have been talking about "C stack hijacking".
This is, from memory size aspects, most efficient, because
you still have only one real stack.
Many platforms suffer from this stack switching, because all
their prediction registers get invalidated.
Interestingly, the X86 seems to be most efficient here,
because its register layout is already as ridiculously dumb
as possible. Therefore, stack switching can be made *very*
efficient on X86 platforms.

In order to combine the benefit of the X86 dumbness with the
typical situation of just some, say, 100 threads (tasklets),
I'm planning to build a stack pool. The stack pool will try to
cover the most frequently used tasklets in a way, that no two
of these live in the same C stack. This doesn't make sense
for huge numbers of tasklets (100.000 and more), here the
soft-switching, and hard-switching with small chunks to
save work the best.
But for high-performance, repeated tasklets, such a stack pool
could outperform typical things like Python generators *by far*:

Right now, a generator frame gets restarted from start every
time it is invoked. This cannot be made better with the past
Stackless features: The best scenario you can get is one frame
on the stack which calls another frame (the generator).
The caller can stay on the stack, but the callee must be re-invoked
all the time. At it's best, Stackless can try to get to this
performance, by the tricks which I tried to explain before.

But a task switch between two C stacks is almost just changing
the EBP and ESP register, plus some crap to change those bad
globals in the thread state, which Prothon hopefully has
avoided. Here you can really get a speed boost of, say, factor
five. This is a special generator mode I'm planning for:
The yield opcode gets a special mode where it doesn't leave the
frame, having to do the complicated re-incarnation stuff,
but where it simply calls a tiny assembly routine which passes
the value over to a different tasklet with a different C stack.

Summarizing: There is a lot what I have implemented, and there
is a lot more that I would like to implement. Prothon has still
the freedom to pick the best of all world. As you have seen,
there is no "one size fits all" solution.
For myriads of tasklets, you will not preserve a 64K segment for
each, but use the stack hijacking idea.
For threads(tasklets) which you need all the time, it is of
course worth spending the extra space.
And even for soft-switched threads, in situations where there are
very many switches, more than the actual computation, it might
make sense to use C stack switching instead of soft-switching,
because the former can be faster, if no data moves are involved.

And this statement is probably not true cross-platform.
There are platforms where changing the C stack is very expensive.
One of them os Spark. I doubt you will change a Spark stack,
unless you really must. :-))

I'd love to have a couple of hours with you in a pub, with paper.

ciao - chris

-- 
Christian Tismer             :^)   <mailto:[email protected]>
Mission Impossible 5oftware  :     Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a     :    *Starship* http://starship.python.net/
14109 Berlin                 :     PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34  home +49 30 802 86 56  mobile +49 173 24 18 776
PGP 0x57F3BF04       9064 F4E1 D754 C2FF 1619  305B C09C 5A3B 57F3 BF04
      whom do you want to sponsor today?   http://www.stackless.com/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.