On 22 September 2010 11:57, Stephane DROUARD <[email protected]> wrote:
> Lisandro Dalcin wrote:
>> > 1/ The simplest, but not the most optimized one: acquire/release the GIL
> within __Pyx_CppExn2PyErr().
>>
>> Why do you say (1) is not the most optimized one? (Sorry, I'm not good
>> at understanding issues with thread-based concurrency)
>
> Because it will acquire/release the GIL, even for functions that are not 
> called
> without "with nogil".
> But maybe acquiring/releasing the GIL is not costy (I haven't checked).
>

I'm not sure about this, either...


>> > 2/ acquire/release the GIL in the catch clause only when "with nogil":
>> >      try {foo();} catch(...) {PyGILState_STATE state = PyGILState_Ensure();
>> __Pyx_CppExn2PyErr(); PyGILState_Release(state); {__pyx_filename = 
>> __pyx_f[0];
> __pyx_lineno = 6;
>> __pyx_clineno = __LINE__; goto __pyx_L6;}}
>> >
>>
>> How would this be different to (1) ?
>
> Because it can only acquires/releases the GIL when a function is called "with
> nogil" and not for the others (but more complex to implement as Cython needs 
> to
> know the "with nogil" context.
>
>> > 3/ restore the thread in the catch clause:
>> >      try {foo();} catch(...) { Py_BLOCK_THREADS __Pyx_CppExn2PyErr();
> {__pyx_filename =
>> __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L6;}}
>> >    }
>> >    /*finally:*/ {
>> >      int __pyx_why;
>> >      Py_BLOCK_THREADS  // <<<<<<<<<<<<<<<<
>> >      __pyx_why = 0; goto __pyx_L7;
>> >      __pyx_L6: __pyx_why = 4; goto __pyx_L7;
>> >      __pyx_L7:;
>> >      switch (__pyx_why) {
>> >        case 4: goto __pyx_L1_error;
>> >      }
>> >    }
>> >  }
>> >
>>
>> And this one looks bad, I think you need: Py_BLOCK_THREADS
>> __Pyx_CppExn2PyErr(); Py_UNBLOCK_THREADS .. Am I right?
>>
>> What about doing this (ignore the line endings, all should be
>> generated in a single line)
>>
>>   { PyThreadState *_save;
>>     try {
>>       Py_UNBLOCK_THREADS
>>       foo();
>>       Py_BLOCK_THREADS
>>     } catch(...) {
>>       Py_BLOCK_THREADS
>>       __Pyx_CppExn2PyErr();
>>     }
>>
>> Am I missing something? However, note that changing to this could be
>> not so easy...
>
> Because you may have several function calls within "with nogil":
> def bar():
>    with nogil:
>        foo()
>        foo()
>
> and the generated code contains as many try/catch around the calls but only 
> one
> thread save/restore:
>  { PyThreadState *_save;
>    Py_UNBLOCK_THREADS
>    /*try:*/ {
>      try {foo();} catch(...) {__Pyx_CppExn2PyErr(); {__pyx_filename =
> __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L6;}}
>      try {foo();} catch(...) {__Pyx_CppExn2PyErr(); {__pyx_filename =
> __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L6;}}
>    }
>    /*finally:*/ {
>      int __pyx_why;
>      __pyx_why = 0; goto __pyx_L7;
>      __pyx_L6: __pyx_why = 4; goto __pyx_L7;
>      __pyx_L7:;
>      Py_BLOCK_THREADS
>      switch (__pyx_why) {
>        case 4: goto __pyx_L1_error;
>      }
>    }
>  }
>

OK, you are definitely right...

A last thing: in my previous mail I commented about fixing you
solution (3) like this:

Py_BLOCK_THREADS
__Pyx_CppExn2PyErr();
Py_UNBLOCK_THREADS

Is that right? Take into account that the /*finally:*/  block does
Py_BLOCK_THREADS...

If you can confirm that this works, I think you solution (3) with my
fix (in case it is fine) is be better option, right?

-- 
Lisandro Dalcin
---------------
CIMEC (INTEC/CONICET-UNL)
Predio CONICET-Santa Fe
Colectora RN 168 Km 472, Paraje El Pozo
Tel: +54-342-4511594 (ext 1011)
Tel/Fax: +54-342-4511169
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to