Parla.py icon indicating copy to clipboard operation
Parla.py copied to clipboard

Tasks can't modify nonlocal variables

Open sestephens73 opened this issue 4 years ago • 3 comments

When a nonlocal variable is modified within a task, the variable's value doesn't actually change outside the scope of the task. As an example:

from parla import Parla
from parla.cpu import cpu
from parla.cuda import gpu
from parla.tasks import *

async def foo():
    a = 1
    print(a)

    @spawn()
    def t1():
        nonlocal a
        print(a)
        a = 2
        print(a)

    await t1
    print(a)

if __name__ == "__main__":
    with Parla():
        @spawn()
        async def bar():
            await foo()

I would expect this to print

1
1
2
2

but instead, it prints

1
1
2
1

sestephens73 avatar Feb 13 '21 18:02 sestephens73

This is a side-effect of the closure capture semantics of Parla tasks (which is different from the closure capture semantics of Python functions). It would be very complex to avoid, since we want changes outside the task to be invisible from inside the task (to allow tasks to be created effectively inside loops among other things). I also think allowing nonlocal changes like this would make the semantics more confusing because of concurrency. I think the correct solution to this is probably to detect this and raise an error. But I'm not the sole designer, so go ahead and debate as you see fit. :-)

arthurp avatar Feb 13 '21 19:02 arthurp

Yah, my only opinion on this is that it shouldn't be doing what it does currently. We need to either disallow the nonlocal and raise an error or allow it to bypass our modified capture semantics. Fortunately nonlocals are something of a niche feature, so there's no rush.

After thinking about this a bit more, I think the only way to do this is to allow the end-user to pass a list of names that they want excluded from our closure-capture hack (https://github.com/ut-parla/Parla.py/blob/d82e6d573a5cd5b1e492a99a0106cd90e632961e/parla/tasks.py#L416). That can be yet another spawn keyword.