Re: [Python-Dev] Coroutines and PEP 380

2012-01-24 Thread Matt Joiner
After much consideration, and playing with PEP380, I've changed my
stance on this. Full blown coroutines are the proper way forward.
greenlet doesn't cut it because the Python interpreter isn't aware of
the context switches. Profiling, debugging and tracebacks are
completely broken by this. Stackless would need to be merged, and
that's clearly not going to happen.

I built a basic scheduler and had a go at enhancing the stdlib using
PEP380, here are some examples making use of this style:
https://bitbucket.org/anacrolix/green380/src/8f7fdc20a8ce/examples

After realising it was a dead-end, I read up on Mark's ideas, there's
some really good stuff in there:
http://www.dcs.gla.ac.uk/~marks/
http://hotpy.blogspot.com/

If someone can explain what's stopping real coroutines being into
Python (3.3), that would be great.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-21 Thread Greg Ewing

Glyph wrote:

Yes, but you /can/ look at a 'yield' and conclude that you /might/ need 
a lock, and that you have to think about it.


My concern is that you will end up with vastly more 'yield from's
than places that require locks, so most of them are just noise.
If you bite your nails over whether a lock is needed every time
you see one, they will cause you a lot more anxiety than they
alleviate.

Sometimes there's no alternative, but wherever I can, I avoid thinking, 
especially hard thinking.  This maxim has served me very well throughout 
my programming career ;-).


There are already well-known techniques for dealing with
concurrency that minimise the amount of hard thinking required.
You devise some well-behaved abstractions, such as queues, and
put all your hard thinking into implementing them. Then you
build the rest of your code around those abstractions. That
way you don't have to rely on crutches such as explicitly
marking everything that might cause a task switch, because
it doesn't matter.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-21 Thread Matt Joiner
 My concern is that you will end up with vastly more 'yield from's
 than places that require locks, so most of them are just noise.
 If you bite your nails over whether a lock is needed every time
 you see one, they will cause you a lot more anxiety than they
 alleviate.

Not necessarily. The yield from's follow the blocking control flow,
which is surprisingly less common than you might think. Parts of your
code naturally arise as not requiring blocking behaviour in the same
manner as in Haskell where parts of your code are identified as
requiring the IO monad.

 Sometimes there's no alternative, but wherever I can, I avoid thinking,
 especially hard thinking.  This maxim has served me very well throughout my
 programming career ;-).

I'd replace hard thinking with future confusion here.

 There are already well-known techniques for dealing with
 concurrency that minimise the amount of hard thinking required.
 You devise some well-behaved abstractions, such as queues, and
 put all your hard thinking into implementing them. Then you
 build the rest of your code around those abstractions. That
 way you don't have to rely on crutches such as explicitly
 marking everything that might cause a task switch, because
 it doesn't matter.

It's my firm belief that this isn't sufficient. If this were true,
then the Python internals could be improved by replacing the GIL with
a series of channels/queues or what have you. State is complex, and
without guarantees of immutability, it's just not practical to try to
wrap every state object in some protocol to be passed back and forth
on queues.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-19 Thread Greg

Glyph wrote:
[Guido] mentions the point that coroutines that can implicitly switch out from 
under you have the same non-deterministic property as threads: you don't 
know where you're going to need a lock or lock-like construct to update 
any variables, so you need to think about concurrency more deeply than 
if you could explicitly always see a 'yield'.


I'm not convinced that being able to see 'yield's will help
all that much. In any system that makes substantial use of
generator-based coroutines, you're going to see 'yield from's
all over the place, from the lowest to the highest levels.
But that doesn't mean you need a correspondingly large
number of locks. You can't look at a 'yield' and conclude
that you need a lock there or tell what needs to be locked.

There's no substitute for deep thought where any kind of
theading is involved, IMO.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-19 Thread Matt Joiner
On Fri, Jan 20, 2012 at 8:41 AM, Greg greg.ew...@canterbury.ac.nz wrote:
 Glyph wrote:

 [Guido] mentions the point that coroutines that can implicitly switch out
 from under you have the same non-deterministic property as threads: you
 don't know where you're going to need a lock or lock-like construct to
 update any variables, so you need to think about concurrency more deeply
 than if you could explicitly always see a 'yield'.


 I'm not convinced that being able to see 'yield's will help
 all that much. In any system that makes substantial use of
 generator-based coroutines, you're going to see 'yield from's
 all over the place, from the lowest to the highest levels.
 But that doesn't mean you need a correspondingly large
 number of locks. You can't look at a 'yield' and conclude
 that you need a lock there or tell what needs to be locked.

 There's no substitute for deep thought where any kind of
 theading is involved, IMO.

 --
 Greg

 ___
 Python-Dev mailing list
 Python-Dev@python.org
 http://mail.python.org/mailman/listinfo/python-dev
 Unsubscribe:
 http://mail.python.org/mailman/options/python-dev/anacrolix%40gmail.com

I wasn't aware that Guido had brought this up, and I believe what he
says to be true. Preemptive coroutines, are just a hack around the
GIL, and reduce OS overheads. It's the explicit nature of the enhanced
generators that is their greatest value.

FWIW, I wrote a Python 3 compatible equivalent to gevent (also
greenlet based, and also very similar to Brett's et al coroutine
proposal), which didn't really solve the concurrency problems I hoped.
There were no guarantees whether functions would switch out, so all
the locking and threading issues simply reemerged, albeit with also
needing to have all calls non-blocking, losing compatibility with any
routine that didn't make use of nonblocking calls and/or expose it's
yield in the correct way, but reducing GIL contention. Overall not
worth it.

In short, implicit coroutines are just a GIL work around, that break
compatibility for little gain.

Thanks Glyph for those links.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-19 Thread Glyph

On Jan 19, 2012, at 4:41 PM, Greg wrote:

 Glyph wrote:
 [Guido] mentions the point that coroutines that can implicitly switch out 
 from under you have the same non-deterministic property as threads: you 
 don't know where you're going to need a lock or lock-like construct to 
 update any variables, so you need to think about concurrency more deeply 
 than if you could explicitly always see a 'yield'.
 
 I'm not convinced that being able to see 'yield's will help
 all that much.

Well, apparently we disagree, and I work on such a system all day, every day 
:-).  It was nice to see that Matt Joiner also agreed for very similar reasons, 
and at least I know I'm not crazy.

 In any system that makes substantial use of
 generator-based coroutines, you're going to see 'yield from's
 all over the place, from the lowest to the highest levels.
 But that doesn't mean you need a correspondingly large
 number of locks. You can't look at a 'yield' and conclude
 that you need a lock there or tell what needs to be locked.

Yes, but you can look at a 'yield' and conclude that you might need a lock, and 
that you have to think about it.

Further exploration of my own feelings on the subject grew a bit beyond a good 
length for a reply here, so if you're interested in my thoughts you can have a 
look at my blog: 
http://glyph.twistedmatrix.com/2012/01/concurrency-spectrum-from-callbacks-to.html.

 There's no substitute for deep thought where any kind of theading is 
 involved, IMO.

Sometimes there's no alternative, but wherever I can, I avoid thinking, 
especially hard thinking.  This maxim has served me very well throughout my 
programming career ;-).

-glyph

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-18 Thread Mark Shannon

Matt Joiner wrote:
Just to clarify, this differs in functionality from enhanced generators 
by allowing you to yield from an arbitrary call depth rather than having 
to yield from through a chain of calling generators? Furthermore 
there's no syntactical change except to the bottommost frame doing a 
co_yield? Does this capture the major differences?



Yes.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-18 Thread Mark Shannon

Glyph wrote:

On Jan 17, 2012, at 5:03 PM, Mark Shannon wrote:


Lets start controversially: I don't like PEP 380, I think it's a kludge.


Too late; it's already accepted.  There's not much point in making 
controversial statements about it now.


Why is it too late? Presenting this as a fait accompli does not make it 
any better. The PEP mailing list is closed to most people, so what forum 
for debate is there?




I think that CPython should have proper coroutines, rather than add 
more bits and pieces to generators in an attempt to make them more 
like coroutines.


By proper coroutines, you mean implicit coroutines (cooperative 
threads) rather than explicit coroutines (cooperative generators). 

Nothing implicit about it.
 Python has been going in the explicit direction on this question for 
a long time.  (And, in my opinion, this is the right direction to go, 
but that's not really relevant here.)


You can use asymmetric coroutines with a scheduler to provide 
cooperative threads if you want, but coroutines not have to be used as 
threads.


The key advantages of my coroutine implmentation over PEP 380 are:

1. No syntax change.
2. Code can be used in coroutines without modification.
3. No stack unwinding is required at a yield point.



I think this discussion would be more suitable for python-ideas though, 
since you have a long row to hoe here.  There's already a PEP - 
http://www.python.org/dev/peps/pep-0219/ - apparently deferred and not 
rejected, which you may want to revisit.


There are several libraries which can give you cooperative threading 
already; I assume you're already aware of greenlet and stackless, but I 
didn't see what advantages your proposed implementation provides over 
those.  I would guess that one of the first things you should address on 
python-ideas is why adopting your implementation would be a better idea 
than just bundling one of those with the standard library :).


Already been discussed:
http://mail.python.org/pipermail/python-ideas/2011-October/012571.html

All of the objections to coroutines (as I propose) also apply to PEP 380.

The advantage of my implementation over greenlets is portability.

I suspect stackless is actually fairly similar to what I have done,
I haven't checked in detail.

Cheers,
Mark.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-18 Thread Glyph
On Jan 18, 2012, at 4:23 AM, Mark Shannon wrote:

 Glyph wrote:
 On Jan 17, 2012, at 5:03 PM, Mark Shannon wrote:
 Lets start controversially: I don't like PEP 380, I think it's a kludge.
 Too late; it's already accepted.  There's not much point in making 
 controversial statements about it now.
 
 Why is it too late?

Because discussion happens before the PEP is accepted.  See the description of 
the workflow in http://www.python.org/dev/peps/pep-0001/.  The time to object 
to PEP 380 was when those threads were going on.

 Presenting this as a fait accompli does not make it any better.

But it is[1] a fait accompli, whether you like it or not; I'm first and 
foremost informing you of the truth, not trying to make you feel better (or 
worse).  Secondly, I am trying to forestall a long and ultimately pointless 
conversation :).

 The PEP mailing list is closed to most people,

The PEP mailing list is just where you submit your PEPs, and where the PEP 
editors do their work.  I'm not on it, but to my understanding of the process, 
there's not really any debate there.

 so what forum for debate is there?

python-ideas, and then this mailing list, in that order.  Regarding PEP 380 
specifically, there's been quite a bit.  See for example 
http://thread.gmane.org/gmane.comp.python.devel/102161/focus=102164.  Keep in 
mind that the purpose of debate in this context is to inform Guido's opinion.  
There's no voting involved, although he will occasionally delegate decisions 
about particular PEPs to people knowledgeable in a relevant area.

 I think this discussion would be more suitable for python-ideas though [...]
 Already been discussed:
 http://mail.python.org/pipermail/python-ideas/2011-October/012571.html

If you're following the PEP process, then the next step would be for you 
(having built some support) to author a new PEP, or to resurrect the deferred 
Stackless PEP with some new rationale - personally I'd recommend the latter.

My brief skimming of the linked thread doesn't indicate you have a lot of 
strong support though, just some people who would be somewhat interested.  So I 
still think it bears more discussion there, especially on the motivation / 
justification side of things.

 All of the objections to coroutines (as I propose) also apply to PEP 380.

You might want to see the video of Guido's Fireside Chat last year 
http://pycon.tv/#/video/100.  Skip to a little before 15:00.  He mentions the 
point that coroutines that can implicitly switch out from under you have the 
same non-deterministic property as threads: you don't know where you're going 
to need a lock or lock-like construct to update any variables, so you need to 
think about concurrency more deeply than if you could explicitly always see a 
'yield'.  I have more than one painful event in my past (as he refers to it) 
indicating that microthreads have the same problem as real threads :).

(And yes, they're microthreads, even if you don't have an elaborate scheduling 
construct.  If you can switch to another stack by making a function call, then 
you are effectively context switching, and it can become arbitrarily complex.  
Any coroutine in a system may introduce an arbitrarily complex microthread 
scheduler just by calling a function that yields to it.)

-glyph

([1]: Well actually it isn't, note the dashed line from Accepted to 
Rejected in the workflow diagram.  But you have to have a really darn good 
reason, and championing the rejection of a pep that Guido has explicitly 
accepted and has liked from pretty much the beginning is going to be very, very 
hard.)

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-18 Thread Matt Joiner
PEP380 and Mark's coroutines could coexist, so I really don't it's
too late matters. Furthermore, PEP380 has utility in its own right
without considering its use for explicit coroutines.

I would like to see these coroutines considered, but as someone else
mentioned, coroutines via PEP380 enhanced generators have some
interesting characteristics, from my experimentations they feel
monadic.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Coroutines and PEP 380

2012-01-17 Thread Mark Shannon

Hi all.

Lets start controversially: I don't like PEP 380, I think it's a kludge.

I think that CPython should have proper coroutines, rather than add more 
bits and pieces to generators in an attempt to make them more like 
coroutines.


I have mentioned this before, but this time I have done something about 
it :)


I have a working, portable, (asymmetric) coroutine implementation here:

https://bitbucket.org/markshannon/hotpy_coroutines

Its all standard C, no messing with the C stack, just using standard 
techniques to convert recursion to iteration
(in the VM not at the Python level) and a revised internal calling 
convention to make CPython stackless:


https://bitbucket.org/markshannon/hotpy_stackless

Then I've added a Coroutine class and fiddled with the implementation of 
YIELD_VALUE to support it.


I think the stackless implementation is pretty solid, but the
coroutine stuff needs some refinement.
I've not tested it well (it passes the test suite, but I've added no new 
tests).

It is (surprisingly) a bit faster than tip (on my machine).
There are limitations: all calls must be Python-to-Python calls,
which rules out most __xxx__ methods. It might be worth special casing 
__iter__, but I've not done that yet.


To try it out:

 import coroutine
To send a value to a coroutine:
 co.send(val)
where co is a Coroutine()
To yield a value:
 coroutine.co_yield(val)
send() is a method, co_yield is a function.

Here's a little program to demonstrate:

import coroutine

class Node:
def __init__(self, l, item, r):
self.l = l
self.item = item
self.r = r

def make_tree(n):
if n == 0:
return Node(None, n, None)
else:
return Node(make_tree(n-1), n, make_tree(n-1))

def walk_tree(t, f):
if t is not None:
walk_tree(t.l, f)
f(t)
walk_tree(t.r, f)

def yielder(t):
coroutine.co_yield(t.item)

def tree_yielder(t):
walk_tree(t, yielder)

co = coroutine.Coroutine(tree_yielder, (make_tree(2),))

while True:
print(co.send(None))

Which will output:

0
1
0
2
0
1
0
None
Traceback (most recent call last):
  File co_demo.py, line 30, in module
print(co.send(None))
TypeError: can't send to a halted coroutine


Cheers,
Mark.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-17 Thread Matt Joiner
Just to clarify, this differs in functionality from enhanced generators by
allowing you to yield from an arbitrary call depth rather than having to
yield from through a chain of calling generators? Furthermore there's no
syntactical change except to the bottommost frame doing a co_yield? Does
this capture the major differences?
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-17 Thread Ethan Furman

Mark Shannon wrote:
I think that CPython should have proper coroutines, rather than add more 
bits and pieces to generators in an attempt to make them more like 
coroutines.


I have mentioned this before, but this time I have done something about 
it :)


I have a working, portable, (asymmetric) coroutine implementation here:

https://bitbucket.org/markshannon/hotpy_coroutines


As a user, this sounds cool!

~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines and PEP 380

2012-01-17 Thread Glyph
On Jan 17, 2012, at 5:03 PM, Mark Shannon wrote:

 Lets start controversially: I don't like PEP 380, I think it's a kludge.

Too late; it's already accepted.  There's not much point in making 
controversial statements about it now.

 I think that CPython should have proper coroutines, rather than add more bits 
 and pieces to generators in an attempt to make them more like coroutines.


By proper coroutines, you mean implicit coroutines (cooperative threads) 
rather than explicit coroutines (cooperative generators).  Python has been 
going in the explicit direction on this question for a long time.  (And, in 
my opinion, this is the right direction to go, but that's not really relevant 
here.)

I think this discussion would be more suitable for python-ideas though, since 
you have a long row to hoe here.  There's already a PEP - 
http://www.python.org/dev/peps/pep-0219/ - apparently deferred and not 
rejected, which you may want to revisit.

There are several libraries which can give you cooperative threading already; I 
assume you're already aware of greenlet and stackless, but I didn't see what 
advantages your proposed implementation provides over those.  I would guess 
that one of the first things you should address on python-ideas is why adopting 
your implementation would be a better idea than just bundling one of those with 
the standard library :).

-glyph

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com