From greg.ewing at canterbury.ac.nz Sun May 1 02:24:29 2011 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Sun, 01 May 2011 12:24:29 +1200 Subject: [Cython] Fused Types In-Reply-To: <4DBC1BA6.3030806@behnel.de> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> Message-ID: <4DBCA83D.6080405@canterbury.ac.nz> Stefan Behnel wrote: > Meaning, we'd find a new type during type analysis > or inference, split off a new version of the function and then analyse > it. I'm not sure that this degree of smartness would really be a good idea. I'd worry that if I made a type error somewhere, the compiler would go off and spend a few hours generating umpteen zillion versions of the code instead of stopping and telling me something was wrong. -- Greg From markflorisson88 at gmail.com Sun May 1 11:38:04 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Sun, 1 May 2011 11:38:04 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBBBF78.4030104@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On 30 April 2011 09:51, Dag Sverre Seljebotn wrote: > On 04/30/2011 08:39 AM, Robert Bradshaw wrote: >> >> On Fri, Apr 29, 2011 at 3:53 AM, mark florisson >> ?wrote: >>> >>> On 29 April 2011 12:28, Pauli Virtanen ?wrote: >>>> >>>> No, just that real_t is specialized to float whenever struct_t is >>>> specialized >>>> to A and to double when B. Or a more realistic example, >>>> >>>> ? ? ? ?ctypedef cython.fused_type(float, double) real_t >>>> ? ? ? ?ctypedef cython.fused_type(float complex, double complex) >>>> complex_t >>>> >>>> ? ? ? ?cdef real_plus_one(complex_t a): >>>> ? ? ? ? ? ?real_t b = a.real >>>> ? ? ? ? ? ?return b + 1 >>>> >>>> which I suppose would not be a very unusual thing in numerical codes. >>>> This would also allow writing the case you had earlier as >>>> >>>> ? ? ? ?cdef cython.fused_type(string_t, int, paired=struct_t) attr_t >>>> >>>> ? ? ? ?cdef func(struct_t mystruct, int i): >>>> ? ? ? ? ? ?cdef attr_t var >>>> >>>> ? ? ? ? ? ?if typeof(mystruct) is typeof(int): >>>> ? ? ? ? ? ? ? ?var = mystruct.attrib + i >>>> ? ? ? ? ? ? ? ?... >>>> ? ? ? ? ? ?else: >>>> ? ? ? ? ? ? ? ?var = mystruct.attrib + i >>>> ? ? ? ? ? ? ? ?... >>>> >>>> Things would need to be done explicitly instead of implicitly, though, >>>> but it would remove the need for any special handling of >>>> the "complex" keyword. >> >> If we're going to introduce pairing, another option would be >> >> ? ? ctypedef fused_type((double complex, double), (float complex, >> float)) (complex_t, real_t) >> >> though I'm not sure I like that either. We're not trying to create the >> all-powerful templating system here, and anything that can be done >> with pairing can be done (though less elegantly) via branching on the >> types, or, as Pauli mentions, using a wider type is often (but not >> always) a viable option. > > Keeping the right balance is difficult. But, at least there's some cases of > needing this in various codebases when interfacing with LAPACK. > > Most uses of templating with Cython code I've seen so far does a similar > kind of "zip" as what you have above (as we discussed on the workshop). So > at least the usage pattern you write above is very common. > > float32 is not about to disappear, it really is twice as fast when you're > memory IO bound. > > Using a wider type is actually quite often not possible; any time the type > is involved as the base type of an array it is not possible, and that's a > pretty common case. Well, if the array is passed into the function directly (and not e.g. as an attribute of something passed in), then you can just write 'my_fused_type *array' or 'my_fused_type array[]', and the base type will be available as 'my_fused_type'. > (With LAPACK you take the address of the variable and > pass it to Fortran, so using a wider type is not possible there either, > although I'll agree that's a more remote case.) > > My proposal: Don't support either "real_t complex" or paired fused types for > the time being. Then see. Ok, sounds good. > But my vote is for paired fused types instead of "real_t complex". > > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > A remaining issue which I'm not quite certain about is the specialization through subscripts, e.g. func[double]. How should this work from Python space (assuming cpdef functions)? Would we want to pass in cython.double etc? Because it would only work for builtin types, so what about types that aren't exposed to Python but can still be coerced to and from Python? Perhaps it would be better to pass in strings instead. I also think e.g. "int *" reads better than cython.pointer(cython.int). It also sounds bad to rely on objects from the Shadow module, as people using Cython modules may not have Cython (or the Shadow module shipped as cython) installed. And what happens if they import it under a different name and we import another cython module? Perhaps the specializations of the signature could also be exposed on the function object, so users can see which ones are available. From sturla at molden.no Sun May 1 15:29:02 2011 From: sturla at molden.no (Sturla Molden) Date: Sun, 01 May 2011 15:29:02 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBCA83D.6080405@canterbury.ac.nz> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> Message-ID: <4DBD601E.2060100@molden.no> Den 01.05.2011 02:24, skrev Greg Ewing: > Stefan Behnel wrote: >> Meaning, we'd find a new type during type analysis or inference, >> split off a new version of the function and then analyse it. > > I'm not sure that this degree of smartness would really > be a good idea. I'd worry that if I made a type error > somewhere, the compiler would go off and spend a few > hours generating umpteen zillion versions of the code > instead of stopping and telling me something was wrong. > I think so too. Cython has a square-bracket syntax for C++ templates. Why not defer the whole problem to the C++ compiler? Just emit the proper C++. Sturla From stefan_ml at behnel.de Sun May 1 16:36:16 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sun, 01 May 2011 16:36:16 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBD601E.2060100@molden.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> Message-ID: <4DBD6FE0.8000200@behnel.de> Sturla Molden, 01.05.2011 15:29: > Den 01.05.2011 02:24, skrev Greg Ewing: >> Stefan Behnel wrote: >>> Meaning, we'd find a new type during type analysis or inference, split >>> off a new version of the function and then analyse it. >> >> I'm not sure that this degree of smartness would really >> be a good idea. I'd worry that if I made a type error >> somewhere, the compiler would go off and spend a few >> hours generating umpteen zillion versions of the code >> instead of stopping and telling me something was wrong. > > I think so too. > > Cython has a square-bracket syntax for C++ templates. Why not defer the > whole problem to the C++ compiler? Just emit the proper C++. Not everyone uses C++. And the C++ compiler cannot adapt the code to specific Python object types. Stefan From sturla at molden.no Sun May 1 18:25:53 2011 From: sturla at molden.no (Sturla Molden) Date: Sun, 01 May 2011 18:25:53 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBD6FE0.8000200@behnel.de> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> Message-ID: <4DBD8991.2030307@molden.no> Den 01.05.2011 16:36, skrev Stefan Behnel: > > Not everyone uses C++. And the C++ compiler cannot adapt the code to > specific Python object types. Ok, that makes sence. Second question: Why not stay with the current square-bracket syntax? Does Cython need a fused-type in addition? I'd also think duck types could be specialised from run-time information? (Cf. profile-guided optimisation.) Sturla From stefan_ml at behnel.de Sun May 1 19:57:04 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sun, 01 May 2011 19:57:04 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBD8991.2030307@molden.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> Message-ID: <4DBD9EF0.7040905@behnel.de> Sturla Molden, 01.05.2011 18:25: > I'd also think duck types could be specialised from run-time information? > (Cf. profile-guided optimisation.) Interesting. That could even be much simpler than WPA. Basically, the profiler would dump the argument types it sees, and then generate a .pxd file with fused types. Stefan From stefan_ml at behnel.de Mon May 2 11:08:38 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 02 May 2011 11:08:38 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> Message-ID: <4DBE7496.8000909@behnel.de> Robert Bradshaw, 30.04.2011 08:16: > On Fri, Apr 29, 2011 at 8:04 AM, mark florisson >> With the type matching it matches on exactly 'if src_type is >> dst_type:' so you can't use 'and' and such... perhaps I should turn >> these expression into a node with the constant value first and then >> see if the result of the entire expression is known at compile time? > > Yes, that's exactly what I was thinking you should do. For now, you could simply (try to) re-run the ConstantFolding transform after the type splitting. It will evaluate constant expressions and also drop unreachable branches from conditionals. Stefan From d.s.seljebotn at astro.uio.no Mon May 2 11:15:13 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Mon, 02 May 2011 11:15:13 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBD8991.2030307@molden.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> Message-ID: <4DBE7621.3080303@astro.uio.no> On 05/01/2011 06:25 PM, Sturla Molden wrote: > Den 01.05.2011 16:36, skrev Stefan Behnel: >> >> Not everyone uses C++. And the C++ compiler cannot adapt the code to >> specific Python object types. > > Ok, that makes sence. > > Second question: Why not stay with the current square-bracket syntax? > Does Cython > need a fused-type in addition? There is no current feature for templates in Cython currently, only interfacing with C++ templates, which is rather different. I.e., your question is very vague. You're welcome to draft your own proposal for full-blown templates in Cython, if that is what you mean. When we came up with this idea, we felt that bringing the full power of C++ templates (including pattern matching etc.) into Cython would be a bit too much; I think Cython devs are above average sceptical to C++ and the mixed blessings of templates. E.g., one reason for not wanting to do it the C++ way is the need to stick largs parts of your program in header files. With fused types, the valid instantiations are determined up front. DS From markflorisson88 at gmail.com Mon May 2 11:22:36 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Mon, 2 May 2011 11:22:36 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBE7496.8000909@behnel.de> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBE7496.8000909@behnel.de> Message-ID: On 2 May 2011 11:08, Stefan Behnel wrote: > Robert Bradshaw, 30.04.2011 08:16: >> >> On Fri, Apr 29, 2011 at 8:04 AM, mark florisson >>> >>> With the type matching it matches on exactly 'if src_type is >>> dst_type:' so you can't use 'and' and such... perhaps I should turn >>> these expression into a node with the constant value first and then >>> see if the result of the entire expression is known at compile time? >> >> Yes, that's exactly what I was thinking you should do. > > For now, you could simply (try to) re-run the ConstantFolding transform > after the type splitting. It will evaluate constant expressions and also > drop unreachable branches from conditionals. Right thanks! I actually ran it on the condition only, as I overlooked its branch pruning capability (sometimes I see 'if (1)' generated code, so that's probably because that happens after ConstantFolding). So wouldn't it be a good idea to just insert another ConstantFolding transform at the end of the pipeline also, and have it recalculate constants in case it was previously determined not_a_constant? > Stefan > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From stefan_ml at behnel.de Mon May 2 12:32:14 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 02 May 2011 12:32:14 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBE7496.8000909@behnel.de> Message-ID: <4DBE882E.5010104@behnel.de> mark florisson, 02.05.2011 11:22: > On 2 May 2011 11:08, Stefan Behnel wrote: >> Robert Bradshaw, 30.04.2011 08:16: >>> >>> On Fri, Apr 29, 2011 at 8:04 AM, mark florisson >>>> >>>> With the type matching it matches on exactly 'if src_type is >>>> dst_type:' so you can't use 'and' and such... perhaps I should turn >>>> these expression into a node with the constant value first and then >>>> see if the result of the entire expression is known at compile time? >>> >>> Yes, that's exactly what I was thinking you should do. >> >> For now, you could simply (try to) re-run the ConstantFolding transform >> after the type splitting. It will evaluate constant expressions and also >> drop unreachable branches from conditionals. > > Right thanks! I actually ran it on the condition only, as I overlooked > its branch pruning capability (sometimes I see 'if (1)' generated > code, so that's probably because that happens after ConstantFolding). ... or because something generates that explicitly (e.g. to simplify some specific code generation), but I couldn't find this with a quick grep right now. I once put a C for-loop into straight sequential argument unpacking code, so that I could "break" out of it at any point, rather than using gotos and labels for that. But that was only half-way hackish because that particular code mimics an unrolled loop anyway. In the future, Vitja's dead code removal branch will handle branch pruning anyway. I just put it into the ConstantFolding transform at the time as it fit in there quite well, and because I thought it would help also during the constant calculation to get rid of dead code while we're at it, e.g. in conditional expressions (x if c else y) or later on in combination with things like the FlattenInList/SwitchTransform. > So wouldn't it be a good idea to just insert another ConstantFolding > transform at the end of the pipeline also, and have it recalculate > constants in case it was previously determined not_a_constant? An additional run would also make sense before the optimisation steps that run after type analysis. Some of them can take advantage of constants, including those created before and during type analysis. Maybe even a third run right before the code generation, i.e. after the optimisations. Not sure if "not_a_constant" values can become a problem. They'll be ignored in the next run, only "constant_value_not_set" values will be recalculated. While newly created expressions will usually be virgins, new values/expressions that are being added to existing "not_a_constant" expressions may end up being ignored, even if the whole expression could then be condensed into a constant. OTOH, these cases may be rare enough to not deserve the additional performance penalty of looking at all expression nodes again. It may be better to call back into ConstantFolding explicitly when generating expressions at a later point, or to just calculate and set the constant values properly while creating the nodes. While you're at it, you can test if it works to reuse the same transform instance for all runs. That should be a tiny bit quicker, because it only needs to build the node dispatch table once (not that I expect it to make any difference, but anyway...). Stefan From markflorisson88 at gmail.com Mon May 2 14:58:47 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Mon, 2 May 2011 14:58:47 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBE882E.5010104@behnel.de> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBE7496.8000909@behnel.de> <4DBE882E.5010104@behnel.de> Message-ID: On 2 May 2011 12:32, Stefan Behnel wrote: > mark florisson, 02.05.2011 11:22: >> >> On 2 May 2011 11:08, Stefan Behnel wrote: >>> >>> Robert Bradshaw, 30.04.2011 08:16: >>>> >>>> On Fri, Apr 29, 2011 at 8:04 AM, mark florisson >>>>> >>>>> With the type matching it matches on exactly 'if src_type is >>>>> dst_type:' so you can't use 'and' and such... perhaps I should turn >>>>> these expression into a node with the constant value first and then >>>>> see if the result of the entire expression is known at compile time? >>>> >>>> Yes, that's exactly what I was thinking you should do. >>> >>> For now, you could simply (try to) re-run the ConstantFolding transform >>> after the type splitting. It will evaluate constant expressions and also >>> drop unreachable branches from conditionals. >> >> Right thanks! I actually ran it on the condition only, as I overlooked >> its branch pruning capability (sometimes I see 'if (1)' generated >> code, so that's probably because that happens after ConstantFolding). > > ... or because something generates that explicitly (e.g. to simplify some > specific code generation), but I couldn't find this with a quick grep right > now. I once put a C for-loop into straight sequential argument unpacking > code, so that I could "break" out of it at any point, rather than using > gotos and labels for that. But that was only half-way hackish because that > particular code mimics an unrolled loop anyway. > > In the future, Vitja's dead code removal branch will handle branch pruning > anyway. I just put it into the ConstantFolding transform at the time as it > fit in there quite well, and because I thought it would help also during the > constant calculation to get rid of dead code while we're at it, e.g. in > conditional expressions (x if c else y) or later on in combination with > things like the FlattenInList/SwitchTransform. > > >> So wouldn't it be a good idea to just insert another ConstantFolding >> transform at the end of the pipeline also, and have it recalculate >> constants in case it was previously determined not_a_constant? > > An additional run would also make sense before the optimisation steps that > run after type analysis. Some of them can take advantage of constants, > including those created before and during type analysis. Maybe even a third > run right before the code generation, i.e. after the optimisations. > > Not sure if "not_a_constant" values can become a problem. They'll be ignored > in the next run, only "constant_value_not_set" values will be recalculated. > While newly created expressions will usually be virgins, new > values/expressions that are being added to existing "not_a_constant" > expressions may end up being ignored, even if the whole expression could > then be condensed into a constant. Right, in my branch I introduced a new instance variable, and if that's true it ignores "not_a_constant" and tries to compute it anyway, as the pruning is mandatory and at the expression was determined "not_a_constant". > OTOH, these cases may be rare enough to not deserve the additional > performance penalty of looking at all expression nodes again. It may be > better to call back into ConstantFolding explicitly when generating > expressions at a later point, or to just calculate and set the constant > values properly while creating the nodes. So far (from what I've seen, I haven't actually done any benchmarks) I think the C compiler is still like 5 times as slow as Cython. > While you're at it, you can test if it works to reuse the same transform > instance for all runs. That should be a tiny bit quicker, because it only > needs to build the node dispatch table once (not that I expect it to make > any difference, but anyway...). Ok, sure. > Stefan > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From sturla at molden.no Mon May 2 15:00:08 2011 From: sturla at molden.no (Sturla Molden) Date: Mon, 02 May 2011 15:00:08 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBE7621.3080303@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> Message-ID: <4DBEAAD8.8000204@molden.no> Den 02.05.2011 11:15, skrev Dag Sverre Seljebotn: > > I.e., your question is very vague. Ok, what I wanted to ask was "why have one syntax for interfacing C++ templates and another for generics?" It seems like syntax bloat to me. > You're welcome to draft your own proposal for full-blown templates in > Cython, if that is what you mean. When we came up with this idea, we > felt that bringing the full power of C++ templates (including pattern > matching etc.) into Cython would be a bit too much; I think Cython > devs are above average sceptical to C++ and the mixed blessings of > templates. > > E.g., one reason for not wanting to do it the C++ way is the need to > stick largs parts of your program in header files. With fused types, > the valid instantiations are determined up front. C++ templates are evil. They require huge header files (compiler dependent, but they all do) and make debugging a night mare. Template metaprogramming in C++ is crazy; we have optimizing compilers for avoiding that. Java and C# has a simpler form of generics, but even that can be too general. Java and C# can specialize code at run-time, because there is a JIT-compiler. Cython must do this in advance, for which fused_types which will give us a combinatoral bloat of specialized code. That is why I suggested using run-time type information from test runs to select those we want. Personally I solve this by "writing code that writes code". It is easy to use a Python script to generate ad print specialized C or Cython code. Sturla From d.s.seljebotn at astro.uio.no Mon May 2 15:07:42 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Mon, 02 May 2011 15:07:42 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBEAAD8.8000204@molden.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> Message-ID: <4DBEAC9E.6020709@astro.uio.no> On 05/02/2011 03:00 PM, Sturla Molden wrote: > Den 02.05.2011 11:15, skrev Dag Sverre Seljebotn: >> >> I.e., your question is very vague. > > Ok, what I wanted to ask was "why have one syntax for interfacing C++ > templates and another for generics?" It seems like syntax bloat to me. But we do that. The CEP specifies that if you have def f(floating x): return x**2 then "f[double]" will refer to the specialization where floating==double, and calling f[double](3.4f) will make the float be upcast to a double. There's no [] within the function definition, but there's no "prior art" for how that would look within Cython. Dag Sverre From d.s.seljebotn at astro.uio.no Mon May 2 15:15:33 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Mon, 02 May 2011 15:15:33 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBEAAD8.8000204@molden.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> Message-ID: <4DBEAE75.9020701@astro.uio.no> On 05/02/2011 03:00 PM, Sturla Molden wrote: > Den 02.05.2011 11:15, skrev Dag Sverre Seljebotn: >> >> I.e., your question is very vague. > > Ok, what I wanted to ask was "why have one syntax for interfacing C++ > templates and another for generics?" It seems like syntax bloat to me. > > >> You're welcome to draft your own proposal for full-blown templates in >> Cython, if that is what you mean. When we came up with this idea, we >> felt that bringing the full power of C++ templates (including pattern >> matching etc.) into Cython would be a bit too much; I think Cython >> devs are above average sceptical to C++ and the mixed blessings of >> templates. >> >> E.g., one reason for not wanting to do it the C++ way is the need to >> stick largs parts of your program in header files. With fused types, >> the valid instantiations are determined up front. > > C++ templates are evil. They require huge header files (compiler > dependent, but they all do) and make debugging a night mare. Template > metaprogramming in C++ is crazy; we have optimizing compilers for > avoiding that. Java and C# has a simpler form of generics, but even that > can be too general. > > Java and C# can specialize code at run-time, because there is a > JIT-compiler. Cython must do this in advance, for which fused_types > which will give us a combinatoral bloat of specialized code. That is why > I suggested using run-time type information from test runs to select > those we want. Well, I think that what you see about "fused_types(object, list)" is mainly theoretical exercises at this point. When fused_types was discussed originally the focus was very much on just finding something that would allow people to specialise for "float,double", or real and complex. IOW, the kind of specializations people would have generated themselves using a templating language anyway. Myself I see typing from profile-assisted compilation as a completely seperate feature (and something that's internal to "cython optimization"), even though they may share most implementation details, and fused types makes such things easier (but so would C++-style templates have done). > Personally I solve this by "writing code that writes code". It is easy > to use a Python script to generate ad print specialized C or Cython code. fused_types is simply a proposal to make people resort to this a little less often (not everybody are comfortable generating source code -- I think everybody reading cython-devel are though). Basically: We don't want C++ templates, but can we extend the language in a way that deals with the most common situations. And fused_types was the compromise we ended up with. DS From robertwb at math.washington.edu Mon May 2 18:24:16 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Mon, 2 May 2011 09:24:16 -0700 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On Sun, May 1, 2011 at 2:38 AM, mark florisson wrote: > On 30 April 2011 09:51, Dag Sverre Seljebotn wrote: >> On 04/30/2011 08:39 AM, Robert Bradshaw wrote: >>> >>> On Fri, Apr 29, 2011 at 3:53 AM, mark florisson >>> ?wrote: >>>> >>>> On 29 April 2011 12:28, Pauli Virtanen ?wrote: >>>>> >>>>> No, just that real_t is specialized to float whenever struct_t is >>>>> specialized >>>>> to A and to double when B. Or a more realistic example, >>>>> >>>>> ? ? ? ?ctypedef cython.fused_type(float, double) real_t >>>>> ? ? ? ?ctypedef cython.fused_type(float complex, double complex) >>>>> complex_t >>>>> >>>>> ? ? ? ?cdef real_plus_one(complex_t a): >>>>> ? ? ? ? ? ?real_t b = a.real >>>>> ? ? ? ? ? ?return b + 1 >>>>> >>>>> which I suppose would not be a very unusual thing in numerical codes. >>>>> This would also allow writing the case you had earlier as >>>>> >>>>> ? ? ? ?cdef cython.fused_type(string_t, int, paired=struct_t) attr_t >>>>> >>>>> ? ? ? ?cdef func(struct_t mystruct, int i): >>>>> ? ? ? ? ? ?cdef attr_t var >>>>> >>>>> ? ? ? ? ? ?if typeof(mystruct) is typeof(int): >>>>> ? ? ? ? ? ? ? ?var = mystruct.attrib + i >>>>> ? ? ? ? ? ? ? ?... >>>>> ? ? ? ? ? ?else: >>>>> ? ? ? ? ? ? ? ?var = mystruct.attrib + i >>>>> ? ? ? ? ? ? ? ?... >>>>> >>>>> Things would need to be done explicitly instead of implicitly, though, >>>>> but it would remove the need for any special handling of >>>>> the "complex" keyword. >>> >>> If we're going to introduce pairing, another option would be >>> >>> ? ? ctypedef fused_type((double complex, double), (float complex, >>> float)) (complex_t, real_t) >>> >>> though I'm not sure I like that either. We're not trying to create the >>> all-powerful templating system here, and anything that can be done >>> with pairing can be done (though less elegantly) via branching on the >>> types, or, as Pauli mentions, using a wider type is often (but not >>> always) a viable option. >> >> Keeping the right balance is difficult. But, at least there's some cases of >> needing this in various codebases when interfacing with LAPACK. >> >> Most uses of templating with Cython code I've seen so far does a similar >> kind of "zip" as what you have above (as we discussed on the workshop). So >> at least the usage pattern you write above is very common. >> >> float32 is not about to disappear, it really is twice as fast when you're >> memory IO bound. >> >> Using a wider type is actually quite often not possible; any time the type >> is involved as the base type of an array it is not possible, and that's a >> pretty common case. > > Well, if the array is passed into the function directly (and not e.g. > as an attribute of something passed in), then you can just write > 'my_fused_type *array' or 'my_fused_type array[]', and the base type > will be available as 'my_fused_type'. > >> (With LAPACK you take the address of the variable and >> pass it to Fortran, so using a wider type is not possible there either, >> although I'll agree that's a more remote case.) >> >> My proposal: Don't support either "real_t complex" or paired fused types for >> the time being. Then see. > > Ok, sounds good. > >> But my vote is for paired fused types instead of "real_t complex". >> >> Dag Sverre >> _______________________________________________ >> cython-devel mailing list >> cython-devel at python.org >> http://mail.python.org/mailman/listinfo/cython-devel >> > > A remaining issue which I'm not quite certain about is the > specialization through subscripts, e.g. func[double]. How should this > work from Python space (assuming cpdef functions)? Would we want to > pass in cython.double etc? Because it would only work for builtin > types, so what about types that aren't exposed to Python but can still > be coerced to and from Python? Perhaps it would be better to pass in > strings instead. I also think e.g. "int *" reads better than > cython.pointer(cython.int). That's whey we offer cython.p_int. On that note, we should support cython.astype("int *") or something like that. Generally, I don't like encoding semantic information in strings. OTHO, since it'll be a mapping of some sort, there's no reason we can't support both. Most of the time it should dispatch (at runtime or compile time) based on the type of the arguments. > It also sounds bad to rely on objects from the Shadow module, as > people using Cython modules may not have Cython (or the Shadow module > shipped as cython) installed. And what happens if they import it under > a different name and we import another cython module? The (vague) idea is that one could ship as much of the cython shadow module with your own code as needed to run without Cython. > Perhaps the > specializations of the signature could also be exposed on the function > object, so users can see which ones are available. Sure. - Robert From markflorisson88 at gmail.com Mon May 2 22:56:44 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Mon, 2 May 2011 22:56:44 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On 2 May 2011 18:24, Robert Bradshaw wrote: > On Sun, May 1, 2011 at 2:38 AM, mark florisson > wrote: >> On 30 April 2011 09:51, Dag Sverre Seljebotn wrote: >>> On 04/30/2011 08:39 AM, Robert Bradshaw wrote: >>>> >>>> On Fri, Apr 29, 2011 at 3:53 AM, mark florisson >>>> ?wrote: >>>>> >>>>> On 29 April 2011 12:28, Pauli Virtanen ?wrote: >>>>>> >>>>>> No, just that real_t is specialized to float whenever struct_t is >>>>>> specialized >>>>>> to A and to double when B. Or a more realistic example, >>>>>> >>>>>> ? ? ? ?ctypedef cython.fused_type(float, double) real_t >>>>>> ? ? ? ?ctypedef cython.fused_type(float complex, double complex) >>>>>> complex_t >>>>>> >>>>>> ? ? ? ?cdef real_plus_one(complex_t a): >>>>>> ? ? ? ? ? ?real_t b = a.real >>>>>> ? ? ? ? ? ?return b + 1 >>>>>> >>>>>> which I suppose would not be a very unusual thing in numerical codes. >>>>>> This would also allow writing the case you had earlier as >>>>>> >>>>>> ? ? ? ?cdef cython.fused_type(string_t, int, paired=struct_t) attr_t >>>>>> >>>>>> ? ? ? ?cdef func(struct_t mystruct, int i): >>>>>> ? ? ? ? ? ?cdef attr_t var >>>>>> >>>>>> ? ? ? ? ? ?if typeof(mystruct) is typeof(int): >>>>>> ? ? ? ? ? ? ? ?var = mystruct.attrib + i >>>>>> ? ? ? ? ? ? ? ?... >>>>>> ? ? ? ? ? ?else: >>>>>> ? ? ? ? ? ? ? ?var = mystruct.attrib + i >>>>>> ? ? ? ? ? ? ? ?... >>>>>> >>>>>> Things would need to be done explicitly instead of implicitly, though, >>>>>> but it would remove the need for any special handling of >>>>>> the "complex" keyword. >>>> >>>> If we're going to introduce pairing, another option would be >>>> >>>> ? ? ctypedef fused_type((double complex, double), (float complex, >>>> float)) (complex_t, real_t) >>>> >>>> though I'm not sure I like that either. We're not trying to create the >>>> all-powerful templating system here, and anything that can be done >>>> with pairing can be done (though less elegantly) via branching on the >>>> types, or, as Pauli mentions, using a wider type is often (but not >>>> always) a viable option. >>> >>> Keeping the right balance is difficult. But, at least there's some cases of >>> needing this in various codebases when interfacing with LAPACK. >>> >>> Most uses of templating with Cython code I've seen so far does a similar >>> kind of "zip" as what you have above (as we discussed on the workshop). So >>> at least the usage pattern you write above is very common. >>> >>> float32 is not about to disappear, it really is twice as fast when you're >>> memory IO bound. >>> >>> Using a wider type is actually quite often not possible; any time the type >>> is involved as the base type of an array it is not possible, and that's a >>> pretty common case. >> >> Well, if the array is passed into the function directly (and not e.g. >> as an attribute of something passed in), then you can just write >> 'my_fused_type *array' or 'my_fused_type array[]', and the base type >> will be available as 'my_fused_type'. >> >>> (With LAPACK you take the address of the variable and >>> pass it to Fortran, so using a wider type is not possible there either, >>> although I'll agree that's a more remote case.) >>> >>> My proposal: Don't support either "real_t complex" or paired fused types for >>> the time being. Then see. >> >> Ok, sounds good. >> >>> But my vote is for paired fused types instead of "real_t complex". >>> >>> Dag Sverre >>> _______________________________________________ >>> cython-devel mailing list >>> cython-devel at python.org >>> http://mail.python.org/mailman/listinfo/cython-devel >>> >> >> A remaining issue which I'm not quite certain about is the >> specialization through subscripts, e.g. func[double]. How should this >> work from Python space (assuming cpdef functions)? Would we want to >> pass in cython.double etc? Because it would only work for builtin >> types, so what about types that aren't exposed to Python but can still >> be coerced to and from Python? Perhaps it would be better to pass in >> strings instead. I also think e.g. "int *" reads better than >> cython.pointer(cython.int). > > That's whey we offer cython.p_int. On that note, we should support > cython.astype("int *") or something like that. Generally, I don't like > encoding semantic information in strings. > > OTHO, since it'll be a mapping of some sort, there's no reason we > can't support both. Most of the time it should dispatch (at runtime or > compile time) based on the type of the arguments. If we have an argument type that is composed of a fused type, would be want the indexing to specify the composed type or the fused type? e.g. ctypedef floating *floating_p cdef func(floating_p x): ... Then do we want func[double](10.0) or func[double_p](10.0) to specialize func? FYI, the type checking works like 'double_p is floating_p' and not 'double is floating_p'. But for functions this is a little different. On the one hand specifying the full types (double_p) makes sense as you're kind of specifying a signature, but on the other hand you're specializing fused types and you don't care how they are composed -- especially if they occur multiple times with different composition. So I'm thinking we want 'func[double]'. >> It also sounds bad to rely on objects from the Shadow module, as >> people using Cython modules may not have Cython (or the Shadow module >> shipped as cython) installed. And what happens if they import it under >> a different name and we import another cython module? > > The (vague) idea is that one could ship as much of the cython shadow > module with your own code as needed to run without Cython. > >> Perhaps the >> specializations of the signature could also be exposed on the function >> object, so users can see which ones are available. > > Sure. > > - Robert > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From robertwb at math.washington.edu Tue May 3 00:21:15 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Mon, 2 May 2011 15:21:15 -0700 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On Mon, May 2, 2011 at 1:56 PM, mark florisson wrote: > On 2 May 2011 18:24, Robert Bradshaw wrote: >> On Sun, May 1, 2011 at 2:38 AM, mark florisson >> wrote: >>> A remaining issue which I'm not quite certain about is the >>> specialization through subscripts, e.g. func[double]. How should this >>> work from Python space (assuming cpdef functions)? Would we want to >>> pass in cython.double etc? Because it would only work for builtin >>> types, so what about types that aren't exposed to Python but can still >>> be coerced to and from Python? Perhaps it would be better to pass in >>> strings instead. I also think e.g. "int *" reads better than >>> cython.pointer(cython.int). >> >> That's whey we offer cython.p_int. On that note, we should support >> cython.astype("int *") or something like that. Generally, I don't like >> encoding semantic information in strings. >> >> OTHO, since it'll be a mapping of some sort, there's no reason we >> can't support both. Most of the time it should dispatch (at runtime or >> compile time) based on the type of the arguments. > > If we have an argument type that is composed of a fused type, would be > want the indexing to specify the composed type or the fused type? e.g. > > ctypedef floating *floating_p How should we support this? It's clear in this case, but only because you chose good names. Another option would be to require parameterization floating_p, with floating_p[floating] the "as-yet-unparameterized" version. Explicit but redundant. (The same applies to struct as classes as well as typedefs.) On the other had, the above is very succinct and clear in context, so I'm leaning towards it. Thoughts? > cdef func(floating_p x): > ? ?... > > Then do we want > > ? ?func[double](10.0) > > or > > ? ?func[double_p](10.0) > > to specialize func? The latter. > FYI, the type checking works like 'double_p is > floating_p' and not 'double is floating_p'. But for functions this is > a little different. On the one hand specifying the full types > (double_p) makes sense as you're kind of specifying a signature, but > on the other hand you're specializing fused types and you don't care > how they are composed -- especially if they occur multiple times with > different composition. So I'm thinking we want 'func[double]'. That's what I'm thinking too. The type you're branching on is floating, and withing that block you can declare variables as floating*, ndarray[dtype=floating], etc. - Robert From robertwb at math.washington.edu Tue May 3 06:24:46 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Mon, 2 May 2011 21:24:46 -0700 Subject: [Cython] Fwd: automatic character conversion problem In-Reply-To: <4DBAC3AD.2030502@astro.rug.nl> References: <4DBAC3AD.2030502@astro.rug.nl> Message-ID: Dear Cython developers, Recently I encountered a problem with Cython's automatic char* to string conversion (Cython version 0.14.1). I'll attach two sample source files. The first one, char2str_a.pyx prints "The quick...", just as I expected. But the second example prints "... lazy dog.". In the original situation I had a call to free() instead of the call to strcpy() which I use here for illustration purposes. Then I got unpredictable results. Apparently the Python string object keeps referring to the C char* a bit longer than I would expect. A previous version (0.11.2) didn't have this problem. Best regards, Hans Terlouw -- J. P. Terlouw Kapteyn Astronomical Institute University of Groningen Postbus 800 NL-9700 AV Groningen The Netherlands Phone: +31-(0)50-3634068/73 Fax: ? +31-(0)50-3636100 Web: ? http://www.astro.rug.nl/~terlouw/ cdef extern from "stdlib.h": ? void free(void* ptr) ? void* malloc(size_t size) cdef extern from "string.h": ? char *strcpy(char *dest, char *src) def char2str(): ? cdef char *c_str_a = malloc(80) ? cdef char *c_str_b = "The quick... ? " ? cdef char *c_str_c = "... lazy dog. ?" ? strcpy(c_str_a, c_str_b) ? p_str = c_str_a ? strcpy(c_str_a, c_str_c) ? p_str = p_str.rstrip() ? print p_str cdef extern from "stdlib.h": ? void free(void* ptr) ? void* malloc(size_t size) cdef extern from "string.h": ? char *strcpy(char *dest, char *src) def char2str(): ? cdef char *c_str_a = malloc(80) ? cdef char *c_str_b = "The quick... ? " ? cdef char *c_str_c = "... lazy dog. ?" ? strcpy(c_str_a, c_str_b) ? p_str = c_str_a ? strcpy(c_str_a, c_str_c) ? print p_str.rstrip() -------------- next part -------------- cdef extern from "stdlib.h": void free(void* ptr) void* malloc(size_t size) cdef extern from "string.h": char *strcpy(char *dest, char *src) def char2str(): cdef char *c_str_a = malloc(80) cdef char *c_str_b = "The quick... " cdef char *c_str_c = "... lazy dog. " strcpy(c_str_a, c_str_b) p_str = c_str_a strcpy(c_str_a, c_str_c) p_str = p_str.rstrip() print p_str -------------- next part -------------- cdef extern from "stdlib.h": void free(void* ptr) void* malloc(size_t size) cdef extern from "string.h": char *strcpy(char *dest, char *src) def char2str(): cdef char *c_str_a = malloc(80) cdef char *c_str_b = "The quick... " cdef char *c_str_c = "... lazy dog. " strcpy(c_str_a, c_str_b) p_str = c_str_a strcpy(c_str_a, c_str_c) print p_str.rstrip() From robertwb at math.washington.edu Tue May 3 06:38:11 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Mon, 2 May 2011 21:38:11 -0700 Subject: [Cython] automatic character conversion problem In-Reply-To: <4DBAC3AD.2030502@astro.rug.nl> References: <4DBAC3AD.2030502@astro.rug.nl> Message-ID: On Fri, Apr 29, 2011 at 6:57 AM, Hans Terlouw wrote: > Dear Cython developers, > > Recently I encountered a problem with Cython's automatic char* to string > conversion (Cython version 0.14.1). I'll attach two sample source files. The > first one, char2str_a.pyx prints "The quick...", just as I expected. But the > second example prints "... lazy dog.". In the original situation I had a > call to > free() instead of the call to strcpy() which I use here for illustration > purposes. Then I got unpredictable results. Apparently the Python string > object > keeps referring to the C char* a bit longer than I would expect. A previous > version (0.11.2) didn't have this problem. This is due to type inference, in the second example, p_str is inferred to be of type char*. - Robert > cdef extern from "stdlib.h": > ? void free(void* ptr) > ? void* malloc(size_t size) > > cdef extern from "string.h": > ? char *strcpy(char *dest, char *src) > > def char2str(): > ? cdef char *c_str_a = malloc(80) > ? cdef char *c_str_b = "The quick... ? " > ? cdef char *c_str_c = "... lazy dog. ?" > > ? strcpy(c_str_a, c_str_b) > > ? p_str = c_str_a > ? strcpy(c_str_a, c_str_c) > ? p_str = p_str.rstrip() > ? print p_str > > > > cdef extern from "stdlib.h": > ? void free(void* ptr) > ? void* malloc(size_t size) > > cdef extern from "string.h": > ? char *strcpy(char *dest, char *src) > > def char2str(): > ? cdef char *c_str_a = malloc(80) > ? cdef char *c_str_b = "The quick... ? " > ? cdef char *c_str_c = "... lazy dog. ?" > > ? strcpy(c_str_a, c_str_b) > > ? p_str = c_str_a > ? strcpy(c_str_a, c_str_c) > ? print p_str.rstrip() > > > > From stefan_ml at behnel.de Tue May 3 06:54:21 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 03 May 2011 06:54:21 +0200 Subject: [Cython] automatic character conversion problem In-Reply-To: References: <4DBAC3AD.2030502@astro.rug.nl> Message-ID: <4DBF8A7D.2050609@behnel.de> [moving this to cython-users] Robert Bradshaw, 03.05.2011 06:38: > On Fri, Apr 29, 2011 at 6:57 AM, Hans Terlouw wrote: >> Recently I encountered a problem with Cython's automatic char* to string >> conversion (Cython version 0.14.1). I'll attach two sample source files. The >> first one, char2str_a.pyx prints "The quick...", just as I expected. But the >> second example prints "... lazy dog.". In the original situation I had a >> call to >> free() instead of the call to strcpy() which I use here for illustration >> purposes. Then I got unpredictable results. Apparently the Python string >> object >> keeps referring to the C char* a bit longer than I would expect. A previous >> version (0.11.2) didn't have this problem. > > This is due to type inference, in the second example, p_str is > inferred to be of type char*. Just to make this a bit clearer: >> cdef extern from "stdlib.h": >> void free(void* ptr) >> void* malloc(size_t size) >> >> cdef extern from "string.h": >> char *strcpy(char *dest, char *src) >> >> def char2str(): >> cdef char *c_str_a =malloc(80) >> cdef char *c_str_b = "The quick... " >> cdef char *c_str_c = "... lazy dog. " >> >> strcpy(c_str_a, c_str_b) >> >> p_str = c_str_a >> strcpy(c_str_a, c_str_c) >> p_str = p_str.rstrip() >> print p_str In this example, p_str is assigned both a char* and a Python object, so type inference makes it a Python object. The first assignment is therefore a copy operation that creates a Python bytes object, and the second operation assigns the object returned from the .rstrip() call. >> cdef extern from "stdlib.h": >> void free(void* ptr) >> void* malloc(size_t size) >> >> cdef extern from "string.h": >> char *strcpy(char *dest, char *src) >> >> def char2str(): >> cdef char *c_str_a =malloc(80) >> cdef char *c_str_b = "The quick... " >> cdef char *c_str_c = "... lazy dog. " >> >> strcpy(c_str_a, c_str_b) >> >> p_str = c_str_a >> strcpy(c_str_a, c_str_c) >> print p_str.rstrip() Here, p_str is only assigned once from a pointer, so the type is inferred as a char*, and the first assignment is a pointer assignment, not a copy operation. You can see the difference with "cython -a", which generates an HTML representation of your code that highlights Python object operations. (Click on a source line to see the C code). Stefan From vitja.makarov at gmail.com Tue May 3 09:03:43 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Tue, 3 May 2011 11:03:43 +0400 Subject: [Cython] Dead code removal Message-ID: Hi! I can move unreachable code removal into its own branch and then make a pull request. But it seems to me that dead code removal should be done in control flow analysis so there are few options: 1. remove unreachable code in control flow transformation 2. set is_terminator flag in control flow and then run removal transformation later For instance, RemoveUnreachableCode doesn't handle this case: try: raise Error finally: pass print 'unreachable' This case could be easily handled if I set is_terminator flag on the whole TryFinallyStatNode, but I'm not sure that this is the only unhandled case. -- vitja. From markflorisson88 at gmail.com Tue May 3 09:59:21 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 09:59:21 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On 3 May 2011 00:21, Robert Bradshaw wrote: > On Mon, May 2, 2011 at 1:56 PM, mark florisson > wrote: >> On 2 May 2011 18:24, Robert Bradshaw wrote: >>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>> wrote: >>>> A remaining issue which I'm not quite certain about is the >>>> specialization through subscripts, e.g. func[double]. How should this >>>> work from Python space (assuming cpdef functions)? Would we want to >>>> pass in cython.double etc? Because it would only work for builtin >>>> types, so what about types that aren't exposed to Python but can still >>>> be coerced to and from Python? Perhaps it would be better to pass in >>>> strings instead. I also think e.g. "int *" reads better than >>>> cython.pointer(cython.int). >>> >>> That's whey we offer cython.p_int. On that note, we should support >>> cython.astype("int *") or something like that. Generally, I don't like >>> encoding semantic information in strings. >>> >>> OTHO, since it'll be a mapping of some sort, there's no reason we >>> can't support both. Most of the time it should dispatch (at runtime or >>> compile time) based on the type of the arguments. >> >> If we have an argument type that is composed of a fused type, would be >> want the indexing to specify the composed type or the fused type? e.g. >> >> ctypedef floating *floating_p > > How should we support this? It's clear in this case, but only because > you chose good names. Another option would be to require > parameterization floating_p, with floating_p[floating] the > "as-yet-unparameterized" version. Explicit but redundant. (The same > applies to struct as classes as well as typedefs.) On the other had, > the above is very succinct and clear in context, so I'm leaning > towards it. Thoughts? Well, it is already supported. floating is fused, so any composition of floating is also fused. >> cdef func(floating_p x): >> ? ?... >> >> Then do we want >> >> ? ?func[double](10.0) >> >> or >> >> ? ?func[double_p](10.0) >> >> to specialize func? > > The latter. I'm really leaning towards the former. What if you write cdef func(floating_p x, floating_p *y): ... Then specializing floating_p using double_p sounds slightly nonsensical, as you're also specializing floating_p *. >> FYI, the type checking works like 'double_p is >> floating_p' and not 'double is floating_p'. But for functions this is >> a little different. On the one hand specifying the full types >> (double_p) makes sense as you're kind of specifying a signature, but >> on the other hand you're specializing fused types and you don't care >> how they are composed -- especially if they occur multiple times with >> different composition. So I'm thinking we want 'func[double]'. > > That's what I'm thinking too. The type you're branching on is > floating, and withing that block you can declare variables as > floating*, ndarray[dtype=floating], etc. What I actually meant there was "I think we want func[double] for the func(floating_p x) signature". Right, people can already say 'cdef func(floating *p): ...' and then use 'floating'. However, if you do 'cdef floating_p x): ...', then 'floating' is not available, only 'floating_p'. It would be rather trivial to also support 'floating' in the latter case, which I think we should, unless you are adamant about prohibiting regular typedefs of fused types. > - Robert > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Tue May 3 10:07:42 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 03 May 2011 10:07:42 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: <4DBFB7CE.4040906@astro.uio.no> On 05/03/2011 09:59 AM, mark florisson wrote: > On 3 May 2011 00:21, Robert Bradshaw wrote: >> On Mon, May 2, 2011 at 1:56 PM, mark florisson >> wrote: >>> On 2 May 2011 18:24, Robert Bradshaw wrote: >>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>> wrote: >>>>> A remaining issue which I'm not quite certain about is the >>>>> specialization through subscripts, e.g. func[double]. How should this >>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>> pass in cython.double etc? Because it would only work for builtin >>>>> types, so what about types that aren't exposed to Python but can still >>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>> strings instead. I also think e.g. "int *" reads better than >>>>> cython.pointer(cython.int). >>>> >>>> That's whey we offer cython.p_int. On that note, we should support >>>> cython.astype("int *") or something like that. Generally, I don't like >>>> encoding semantic information in strings. >>>> >>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>> can't support both. Most of the time it should dispatch (at runtime or >>>> compile time) based on the type of the arguments. >>> >>> If we have an argument type that is composed of a fused type, would be >>> want the indexing to specify the composed type or the fused type? e.g. >>> >>> ctypedef floating *floating_p >> >> How should we support this? It's clear in this case, but only because >> you chose good names. Another option would be to require >> parameterization floating_p, with floating_p[floating] the >> "as-yet-unparameterized" version. Explicit but redundant. (The same >> applies to struct as classes as well as typedefs.) On the other had, >> the above is very succinct and clear in context, so I'm leaning >> towards it. Thoughts? > > Well, it is already supported. floating is fused, so any composition > of floating is also fused. > >>> cdef func(floating_p x): >>> ... >>> >>> Then do we want >>> >>> func[double](10.0) >>> >>> or >>> >>> func[double_p](10.0) >>> >>> to specialize func? >> >> The latter. > > I'm really leaning towards the former. What if you write > > cdef func(floating_p x, floating_p *y): > ... > > Then specializing floating_p using double_p sounds slightly > nonsensical, as you're also specializing floating_p *. I made myself agree with both of you in turn, but in the end I think I'm with Robert here. Robert's approach sounds perhaps slightly simpler if you think of it this way: ctypedef fused_type(float, double) floating ctypedef floating* floating_p is really a short-hand for ctypedef fused_type(float*, double*) floating_p I.e., when using a fused_type in a typedef you simply get a new fused_type. This sounds in a sense simpler without extra complexity getting in the way ("which was my fused base type again..."). Dag SVerre From markflorisson88 at gmail.com Tue May 3 10:42:07 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 10:42:07 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBFB7CE.4040906@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> <4DBFB7CE.4040906@astro.uio.no> Message-ID: On 3 May 2011 10:07, Dag Sverre Seljebotn wrote: > On 05/03/2011 09:59 AM, mark florisson wrote: >> >> On 3 May 2011 00:21, Robert Bradshaw ?wrote: >>> >>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>> ?wrote: >>>> >>>> On 2 May 2011 18:24, Robert Bradshaw >>>> ?wrote: >>>>> >>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>> ?wrote: >>>>>> >>>>>> A remaining issue which I'm not quite certain about is the >>>>>> specialization through subscripts, e.g. func[double]. How should this >>>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>> types, so what about types that aren't exposed to Python but can still >>>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>> cython.pointer(cython.int). >>>>> >>>>> That's whey we offer cython.p_int. On that note, we should support >>>>> cython.astype("int *") or something like that. Generally, I don't like >>>>> encoding semantic information in strings. >>>>> >>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>> can't support both. Most of the time it should dispatch (at runtime or >>>>> compile time) based on the type of the arguments. >>>> >>>> If we have an argument type that is composed of a fused type, would be >>>> want the indexing to specify the composed type or the fused type? e.g. >>>> >>>> ctypedef floating *floating_p >>> >>> How should we support this? It's clear in this case, but only because >>> you chose good names. Another option would be to require >>> parameterization floating_p, with floating_p[floating] the >>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>> applies to struct as classes as well as typedefs.) On the other had, >>> the above is very succinct and clear in context, so I'm leaning >>> towards it. Thoughts? >> >> Well, it is already supported. floating is fused, so any composition >> of floating is also fused. >> >>>> cdef func(floating_p x): >>>> ? ?... >>>> >>>> Then do we want >>>> >>>> ? ?func[double](10.0) >>>> >>>> or >>>> >>>> ? ?func[double_p](10.0) >>>> >>>> to specialize func? >>> >>> The latter. >> >> I'm really leaning towards the former. What if you write >> >> cdef func(floating_p x, floating_p *y): >> ? ? ... >> >> Then specializing floating_p using double_p sounds slightly >> nonsensical, as you're also specializing floating_p *. > > I made myself agree with both of you in turn, but in the end I think I'm > with Robert here. > > Robert's approach sounds perhaps slightly simpler if you think of it this > way: > > ctypedef fused_type(float, double) floating > ctypedef floating* floating_p > > is really a short-hand for > > ctypedef fused_type(float*, double*) floating_p > > I.e., when using a fused_type in a typedef you simply get a new fused_type. > This sounds in a sense simpler without extra complexity getting in the way > ("which was my fused base type again..."). > > Dag SVerre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > Ok, if those typedefs should be disallowed then specialization through indexing should then definitely get the types listed in the fused_type typedef. From d.s.seljebotn at astro.uio.no Tue May 3 10:44:42 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 03 May 2011 10:44:42 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DBBBF78.4030104@astro.uio.no> <4DBFB7CE.4040906@astro.uio.no> Message-ID: <4DBFC07A.1060600@astro.uio.no> On 05/03/2011 10:42 AM, mark florisson wrote: > On 3 May 2011 10:07, Dag Sverre Seljebotn wrote: >> On 05/03/2011 09:59 AM, mark florisson wrote: >>> >>> On 3 May 2011 00:21, Robert Bradshaw wrote: >>>> >>>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>>> wrote: >>>>> >>>>> On 2 May 2011 18:24, Robert Bradshaw >>>>> wrote: >>>>>> >>>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>>> wrote: >>>>>>> >>>>>>> A remaining issue which I'm not quite certain about is the >>>>>>> specialization through subscripts, e.g. func[double]. How should this >>>>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>>> types, so what about types that aren't exposed to Python but can still >>>>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>>> cython.pointer(cython.int). >>>>>> >>>>>> That's whey we offer cython.p_int. On that note, we should support >>>>>> cython.astype("int *") or something like that. Generally, I don't like >>>>>> encoding semantic information in strings. >>>>>> >>>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>>> can't support both. Most of the time it should dispatch (at runtime or >>>>>> compile time) based on the type of the arguments. >>>>> >>>>> If we have an argument type that is composed of a fused type, would be >>>>> want the indexing to specify the composed type or the fused type? e.g. >>>>> >>>>> ctypedef floating *floating_p >>>> >>>> How should we support this? It's clear in this case, but only because >>>> you chose good names. Another option would be to require >>>> parameterization floating_p, with floating_p[floating] the >>>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>>> applies to struct as classes as well as typedefs.) On the other had, >>>> the above is very succinct and clear in context, so I'm leaning >>>> towards it. Thoughts? >>> >>> Well, it is already supported. floating is fused, so any composition >>> of floating is also fused. >>> >>>>> cdef func(floating_p x): >>>>> ... >>>>> >>>>> Then do we want >>>>> >>>>> func[double](10.0) >>>>> >>>>> or >>>>> >>>>> func[double_p](10.0) >>>>> >>>>> to specialize func? >>>> >>>> The latter. >>> >>> I'm really leaning towards the former. What if you write >>> >>> cdef func(floating_p x, floating_p *y): >>> ... >>> >>> Then specializing floating_p using double_p sounds slightly >>> nonsensical, as you're also specializing floating_p *. >> >> I made myself agree with both of you in turn, but in the end I think I'm >> with Robert here. >> >> Robert's approach sounds perhaps slightly simpler if you think of it this >> way: >> >> ctypedef fused_type(float, double) floating >> ctypedef floating* floating_p >> >> is really a short-hand for >> >> ctypedef fused_type(float*, double*) floating_p >> >> I.e., when using a fused_type in a typedef you simply get a new fused_type. >> This sounds in a sense simpler without extra complexity getting in the way >> ("which was my fused base type again..."). >> >> Dag SVerre >> _______________________________________________ >> cython-devel mailing list >> cython-devel at python.org >> http://mail.python.org/mailman/listinfo/cython-devel >> > > Ok, if those typedefs should be disallowed then specialization through > indexing should then definitely get the types listed in the fused_type > typedef. I'm not sure what you mean here. What is disallowed exactly? DS From markflorisson88 at gmail.com Tue May 3 10:49:43 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 10:49:43 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBFC07A.1060600@astro.uio.no> References: <4DBBBF78.4030104@astro.uio.no> <4DBFB7CE.4040906@astro.uio.no> <4DBFC07A.1060600@astro.uio.no> Message-ID: On 3 May 2011 10:44, Dag Sverre Seljebotn wrote: > On 05/03/2011 10:42 AM, mark florisson wrote: >> >> On 3 May 2011 10:07, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/03/2011 09:59 AM, mark florisson wrote: >>>> >>>> On 3 May 2011 00:21, Robert Bradshaw >>>> ?wrote: >>>>> >>>>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>>>> ? ?wrote: >>>>>> >>>>>> On 2 May 2011 18:24, Robert Bradshaw >>>>>> ?wrote: >>>>>>> >>>>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>>>> ? ?wrote: >>>>>>>> >>>>>>>> A remaining issue which I'm not quite certain about is the >>>>>>>> specialization through subscripts, e.g. func[double]. How should >>>>>>>> this >>>>>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>>>> types, so what about types that aren't exposed to Python but can >>>>>>>> still >>>>>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>>>> cython.pointer(cython.int). >>>>>>> >>>>>>> That's whey we offer cython.p_int. On that note, we should support >>>>>>> cython.astype("int *") or something like that. Generally, I don't >>>>>>> like >>>>>>> encoding semantic information in strings. >>>>>>> >>>>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>>>> can't support both. Most of the time it should dispatch (at runtime >>>>>>> or >>>>>>> compile time) based on the type of the arguments. >>>>>> >>>>>> If we have an argument type that is composed of a fused type, would be >>>>>> want the indexing to specify the composed type or the fused type? e.g. >>>>>> >>>>>> ctypedef floating *floating_p >>>>> >>>>> How should we support this? It's clear in this case, but only because >>>>> you chose good names. Another option would be to require >>>>> parameterization floating_p, with floating_p[floating] the >>>>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>>>> applies to struct as classes as well as typedefs.) On the other had, >>>>> the above is very succinct and clear in context, so I'm leaning >>>>> towards it. Thoughts? >>>> >>>> Well, it is already supported. floating is fused, so any composition >>>> of floating is also fused. >>>> >>>>>> cdef func(floating_p x): >>>>>> ? ?... >>>>>> >>>>>> Then do we want >>>>>> >>>>>> ? ?func[double](10.0) >>>>>> >>>>>> or >>>>>> >>>>>> ? ?func[double_p](10.0) >>>>>> >>>>>> to specialize func? >>>>> >>>>> The latter. >>>> >>>> I'm really leaning towards the former. What if you write >>>> >>>> cdef func(floating_p x, floating_p *y): >>>> ? ? ... >>>> >>>> Then specializing floating_p using double_p sounds slightly >>>> nonsensical, as you're also specializing floating_p *. >>> >>> I made myself agree with both of you in turn, but in the end I think I'm >>> with Robert here. >>> >>> Robert's approach sounds perhaps slightly simpler if you think of it this >>> way: >>> >>> ctypedef fused_type(float, double) floating >>> ctypedef floating* floating_p >>> >>> is really a short-hand for >>> >>> ctypedef fused_type(float*, double*) floating_p >>> >>> I.e., when using a fused_type in a typedef you simply get a new >>> fused_type. >>> This sounds in a sense simpler without extra complexity getting in the >>> way >>> ("which was my fused base type again..."). >>> >>> Dag SVerre >>> _______________________________________________ >>> cython-devel mailing list >>> cython-devel at python.org >>> http://mail.python.org/mailman/listinfo/cython-devel >>> >> >> Ok, if those typedefs should be disallowed then specialization through >> indexing should then definitely get the types listed in the fused_type >> typedef. > > I'm not sure what you mean here. What is disallowed exactly? ctypedef cython.fused_type(float, double) floating ctypedef floating *floating_p That is what you meant right? Because prohibiting that makes it easier to see where a type is variable (as the entire type always is, and not some base type of it). > DS > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Tue May 3 10:57:40 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 03 May 2011 10:57:40 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DBBBF78.4030104@astro.uio.no> <4DBFB7CE.4040906@astro.uio.no> <4DBFC07A.1060600@astro.uio.no> Message-ID: <4DBFC384.5000209@astro.uio.no> On 05/03/2011 10:49 AM, mark florisson wrote: > On 3 May 2011 10:44, Dag Sverre Seljebotn wrote: >> On 05/03/2011 10:42 AM, mark florisson wrote: >>> >>> On 3 May 2011 10:07, Dag Sverre Seljebotn >>> wrote: >>>> >>>> On 05/03/2011 09:59 AM, mark florisson wrote: >>>>> >>>>> On 3 May 2011 00:21, Robert Bradshaw >>>>> wrote: >>>>>> >>>>>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>>>>> wrote: >>>>>>> >>>>>>> On 2 May 2011 18:24, Robert Bradshaw >>>>>>> wrote: >>>>>>>> >>>>>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>>>>> wrote: >>>>>>>>> >>>>>>>>> A remaining issue which I'm not quite certain about is the >>>>>>>>> specialization through subscripts, e.g. func[double]. How should >>>>>>>>> this >>>>>>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>>>>> types, so what about types that aren't exposed to Python but can >>>>>>>>> still >>>>>>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>>>>> cython.pointer(cython.int). >>>>>>>> >>>>>>>> That's whey we offer cython.p_int. On that note, we should support >>>>>>>> cython.astype("int *") or something like that. Generally, I don't >>>>>>>> like >>>>>>>> encoding semantic information in strings. >>>>>>>> >>>>>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>>>>> can't support both. Most of the time it should dispatch (at runtime >>>>>>>> or >>>>>>>> compile time) based on the type of the arguments. >>>>>>> >>>>>>> If we have an argument type that is composed of a fused type, would be >>>>>>> want the indexing to specify the composed type or the fused type? e.g. >>>>>>> >>>>>>> ctypedef floating *floating_p >>>>>> >>>>>> How should we support this? It's clear in this case, but only because >>>>>> you chose good names. Another option would be to require >>>>>> parameterization floating_p, with floating_p[floating] the >>>>>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>>>>> applies to struct as classes as well as typedefs.) On the other had, >>>>>> the above is very succinct and clear in context, so I'm leaning >>>>>> towards it. Thoughts? >>>>> >>>>> Well, it is already supported. floating is fused, so any composition >>>>> of floating is also fused. >>>>> >>>>>>> cdef func(floating_p x): >>>>>>> ... >>>>>>> >>>>>>> Then do we want >>>>>>> >>>>>>> func[double](10.0) >>>>>>> >>>>>>> or >>>>>>> >>>>>>> func[double_p](10.0) >>>>>>> >>>>>>> to specialize func? >>>>>> >>>>>> The latter. >>>>> >>>>> I'm really leaning towards the former. What if you write >>>>> >>>>> cdef func(floating_p x, floating_p *y): >>>>> ... >>>>> >>>>> Then specializing floating_p using double_p sounds slightly >>>>> nonsensical, as you're also specializing floating_p *. >>>> >>>> I made myself agree with both of you in turn, but in the end I think I'm >>>> with Robert here. >>>> >>>> Robert's approach sounds perhaps slightly simpler if you think of it this >>>> way: >>>> >>>> ctypedef fused_type(float, double) floating >>>> ctypedef floating* floating_p >>>> >>>> is really a short-hand for >>>> >>>> ctypedef fused_type(float*, double*) floating_p >>>> >>>> I.e., when using a fused_type in a typedef you simply get a new >>>> fused_type. >>>> This sounds in a sense simpler without extra complexity getting in the >>>> way >>>> ("which was my fused base type again..."). >>>> >>>> Dag SVerre >>>> _______________________________________________ >>>> cython-devel mailing list >>>> cython-devel at python.org >>>> http://mail.python.org/mailman/listinfo/cython-devel >>>> >>> >>> Ok, if those typedefs should be disallowed then specialization through >>> indexing should then definitely get the types listed in the fused_type >>> typedef. >> >> I'm not sure what you mean here. What is disallowed exactly? > > ctypedef cython.fused_type(float, double) floating > ctypedef floating *floating_p > > That is what you meant right? Because prohibiting that makes it easier > to see where a type is variable (as the entire type always is, and not > some base type of it). No. I meant that the above is automatically transformed into ctypedef cython.fused_type(float, double) floating ctypedef cython.fused_type(float*, double*) floating_p DS From markflorisson88 at gmail.com Tue May 3 11:02:56 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 11:02:56 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBFC384.5000209@astro.uio.no> References: <4DBBBF78.4030104@astro.uio.no> <4DBFB7CE.4040906@astro.uio.no> <4DBFC07A.1060600@astro.uio.no> <4DBFC384.5000209@astro.uio.no> Message-ID: On 3 May 2011 10:57, Dag Sverre Seljebotn wrote: > On 05/03/2011 10:49 AM, mark florisson wrote: >> >> On 3 May 2011 10:44, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/03/2011 10:42 AM, mark florisson wrote: >>>> >>>> On 3 May 2011 10:07, Dag Sverre Seljebotn >>>> ?wrote: >>>>> >>>>> On 05/03/2011 09:59 AM, mark florisson wrote: >>>>>> >>>>>> On 3 May 2011 00:21, Robert Bradshaw >>>>>> ?wrote: >>>>>>> >>>>>>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>>>>>> ? ? ?wrote: >>>>>>>> >>>>>>>> On 2 May 2011 18:24, Robert Bradshaw >>>>>>>> ?wrote: >>>>>>>>> >>>>>>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>>>>>> ? ? ?wrote: >>>>>>>>>> >>>>>>>>>> A remaining issue which I'm not quite certain about is the >>>>>>>>>> specialization through subscripts, e.g. func[double]. How should >>>>>>>>>> this >>>>>>>>>> work from Python space (assuming cpdef functions)? Would we want >>>>>>>>>> to >>>>>>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>>>>>> types, so what about types that aren't exposed to Python but can >>>>>>>>>> still >>>>>>>>>> be coerced to and from Python? Perhaps it would be better to pass >>>>>>>>>> in >>>>>>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>>>>>> cython.pointer(cython.int). >>>>>>>>> >>>>>>>>> That's whey we offer cython.p_int. On that note, we should support >>>>>>>>> cython.astype("int *") or something like that. Generally, I don't >>>>>>>>> like >>>>>>>>> encoding semantic information in strings. >>>>>>>>> >>>>>>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>>>>>> can't support both. Most of the time it should dispatch (at runtime >>>>>>>>> or >>>>>>>>> compile time) based on the type of the arguments. >>>>>>>> >>>>>>>> If we have an argument type that is composed of a fused type, would >>>>>>>> be >>>>>>>> want the indexing to specify the composed type or the fused type? >>>>>>>> e.g. >>>>>>>> >>>>>>>> ctypedef floating *floating_p >>>>>>> >>>>>>> How should we support this? It's clear in this case, but only because >>>>>>> you chose good names. Another option would be to require >>>>>>> parameterization floating_p, with floating_p[floating] the >>>>>>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>>>>>> applies to struct as classes as well as typedefs.) On the other had, >>>>>>> the above is very succinct and clear in context, so I'm leaning >>>>>>> towards it. Thoughts? >>>>>> >>>>>> Well, it is already supported. floating is fused, so any composition >>>>>> of floating is also fused. >>>>>> >>>>>>>> cdef func(floating_p x): >>>>>>>> ? ?... >>>>>>>> >>>>>>>> Then do we want >>>>>>>> >>>>>>>> ? ?func[double](10.0) >>>>>>>> >>>>>>>> or >>>>>>>> >>>>>>>> ? ?func[double_p](10.0) >>>>>>>> >>>>>>>> to specialize func? >>>>>>> >>>>>>> The latter. >>>>>> >>>>>> I'm really leaning towards the former. What if you write >>>>>> >>>>>> cdef func(floating_p x, floating_p *y): >>>>>> ? ? ... >>>>>> >>>>>> Then specializing floating_p using double_p sounds slightly >>>>>> nonsensical, as you're also specializing floating_p *. >>>>> >>>>> I made myself agree with both of you in turn, but in the end I think >>>>> I'm >>>>> with Robert here. >>>>> >>>>> Robert's approach sounds perhaps slightly simpler if you think of it >>>>> this >>>>> way: >>>>> >>>>> ctypedef fused_type(float, double) floating >>>>> ctypedef floating* floating_p >>>>> >>>>> is really a short-hand for >>>>> >>>>> ctypedef fused_type(float*, double*) floating_p >>>>> >>>>> I.e., when using a fused_type in a typedef you simply get a new >>>>> fused_type. >>>>> This sounds in a sense simpler without extra complexity getting in the >>>>> way >>>>> ("which was my fused base type again..."). >>>>> >>>>> Dag SVerre >>>>> _______________________________________________ >>>>> cython-devel mailing list >>>>> cython-devel at python.org >>>>> http://mail.python.org/mailman/listinfo/cython-devel >>>>> >>>> >>>> Ok, if those typedefs should be disallowed then specialization through >>>> indexing should then definitely get the types listed in the fused_type >>>> typedef. >>> >>> I'm not sure what you mean here. What is disallowed exactly? >> >> ctypedef cython.fused_type(float, double) floating >> ctypedef floating *floating_p >> >> That is what you meant right? Because prohibiting that makes it easier >> to see where a type is variable (as the entire type always is, and not >> some base type of it). > > > No. I meant that the above is automatically transformed into > > ctypedef cython.fused_type(float, double) floating > ctypedef cython.fused_type(float*, double*) floating_p I see, so you want to allow it but you consider the entire thing variable. Ok sure, in a way it makes as much sense as the other. So then 'floating *' would get specialized using 'double', and 'floating_p' would get specialized using 'double_p'. > > DS > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From greg.ewing at canterbury.ac.nz Tue May 3 07:47:58 2011 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Tue, 03 May 2011 17:47:58 +1200 Subject: [Cython] Fused Types In-Reply-To: <4DBEAE75.9020701@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> Message-ID: <4DBF970E.9050407@canterbury.ac.nz> I'm a bit confused about how fused types combine to create further fused types. If you have something like ctypedef struct Vector: floating x floating y floating z then is it going to generate code for all possible combinations of types for x, y and z? That's probably not what the user intended -- it's more likely that he wants *two* versions of type Vector, one with all floats and one with all doubles. But without explicit type parameters, there's no way to express that. I worry that you're introducing a parameterised type system in a half-baked way here without properly thinking through all the implications. -- Greg From markflorisson88 at gmail.com Tue May 3 15:17:39 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 15:17:39 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DBF970E.9050407@canterbury.ac.nz> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> Message-ID: On 3 May 2011 07:47, Greg Ewing wrote: > I'm a bit confused about how fused types combine to > create further fused types. If you have something > like > > ?ctypedef struct Vector: > ? ?floating x > ? ?floating y > ? ?floating z > > then is it going to generate code for all possible > combinations of types for x, y and z? > > That's probably not what the user intended -- it's > more likely that he wants *two* versions of type > Vector, one with all floats and one with all doubles. > But without explicit type parameters, there's no way > to express that. > > I worry that you're introducing a parameterised type > system in a half-baked way here without properly > thinking through all the implications. > > -- > Greg > > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > Currently you cannot use them at all in structs, only as cdef function argument types. Then if you have cdef func(floating x, floating y): ... you get a "float, float" version, and a "double, double" version, but not "float, double" or "double, float". When and if support for structs is there, it will work the same way as with functions. From markflorisson88 at gmail.com Tue May 3 15:19:42 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 15:19:42 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> Message-ID: On 3 May 2011 15:17, mark florisson wrote: > On 3 May 2011 07:47, Greg Ewing wrote: >> I'm a bit confused about how fused types combine to >> create further fused types. If you have something >> like >> >> ?ctypedef struct Vector: >> ? ?floating x >> ? ?floating y >> ? ?floating z >> >> then is it going to generate code for all possible >> combinations of types for x, y and z? >> >> That's probably not what the user intended -- it's >> more likely that he wants *two* versions of type >> Vector, one with all floats and one with all doubles. >> But without explicit type parameters, there's no way >> to express that. >> >> I worry that you're introducing a parameterised type >> system in a half-baked way here without properly >> thinking through all the implications. >> >> -- >> Greg >> >> _______________________________________________ >> cython-devel mailing list >> cython-devel at python.org >> http://mail.python.org/mailman/listinfo/cython-devel >> > > Currently you cannot use them at all in structs, only as cdef function > argument types. Then if you have > > cdef func(floating x, floating y): > ? ?... > > you get a "float, float" version, and a "double, double" version, but > not "float, double" or "double, float". When and if support for > structs is there, it will work the same way as with functions. > However the difference here is a ctypedef: ctypedef floating *floating_p Now a parameter with floating_p may have a different specialized base type than the specialized type of floating. From stefan_ml at behnel.de Tue May 3 15:51:30 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 03 May 2011 15:51:30 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> Message-ID: <4DC00862.6030603@behnel.de> mark florisson, 03.05.2011 15:17: > if you have > > cdef func(floating x, floating y): > ... > > you get a "float, float" version, and a "double, double" version, but > not "float, double" or "double, float". So, what would you have to do in order to get a "float, double" and "double, float" version then? Could you get that with ctypedef fused_type(double, float) floating_df ctypedef fused_type(float, double) floating_fd cdef func(floating_df x, floating_fd y): ? I assume there's no special casing for floating point types in the compiler, is there? Stefan From d.s.seljebotn at astro.uio.no Tue May 3 16:06:05 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 03 May 2011 16:06:05 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DC00862.6030603@behnel.de> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC00862.6030603@behnel.de> Message-ID: <4DC00BCD.7090508@astro.uio.no> On 05/03/2011 03:51 PM, Stefan Behnel wrote: > mark florisson, 03.05.2011 15:17: >> if you have >> >> cdef func(floating x, floating y): >> ... >> >> you get a "float, float" version, and a "double, double" version, but >> not "float, double" or "double, float". > > So, what would you have to do in order to get a "float, double" and > "double, float" version then? Could you get that with > > ctypedef fused_type(double, float) floating_df > ctypedef fused_type(float, double) floating_fd > > cdef func(floating_df x, floating_fd y): > > ? Well, if you do something like ctypedef fused_type(float, double) speed_t ctypedef fused_type(float, double) acceleration_t cdef func(speed_t x, acceleration_t y) then you get 4 specializations. Each new typedef gives a new polymorphic type. OTOH, with ctypedef speed_t acceleration_t I guess only 2 specializations. Treating the typedefs in this way is slightly fishy of course. It may hint that "ctypedef" is the wrong way to declare a fused type *shrug*. To only get the "cross-versions" you'd need something like what you wrote + Pauli's "paired"-suggestion. Dag Sverre From sturla at molden.no Tue May 3 16:36:31 2011 From: sturla at molden.no (Sturla Molden) Date: Tue, 03 May 2011 16:36:31 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DC00BCD.7090508@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC00862.6030603@behnel.de> <4DC00BCD.7090508@astro.uio.no> Message-ID: <4DC012EF.3030306@molden.no> Den 03.05.2011 16:06, skrev Dag Sverre Seljebotn: > > Well, if you do something like > > ctypedef fused_type(float, double) speed_t > ctypedef fused_type(float, double) acceleration_t > > cdef func(speed_t x, acceleration_t y) > > then you get 4 specializations. Each new typedef gives a new > polymorphic type. > > OTOH, with > > ctypedef speed_t acceleration_t > > I guess only 2 specializations. > > Treating the typedefs in this way is slightly fishy of course. It may > hint that "ctypedef" is the wrong way to declare a fused type *shrug*. > > To only get the "cross-versions" you'd need something like what you > wrote + Pauli's "paired"-suggestion. > This is a bloatware generator. It might not be used right, or it might generate bloat due to small mistakes (which will go unnoticed/silent). Sturla From robertwb at math.washington.edu Tue May 3 18:00:40 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 3 May 2011 09:00:40 -0700 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On Tue, May 3, 2011 at 12:59 AM, mark florisson wrote: > On 3 May 2011 00:21, Robert Bradshaw wrote: >> On Mon, May 2, 2011 at 1:56 PM, mark florisson >> wrote: >>> On 2 May 2011 18:24, Robert Bradshaw wrote: >>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>> wrote: >>>>> A remaining issue which I'm not quite certain about is the >>>>> specialization through subscripts, e.g. func[double]. How should this >>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>> pass in cython.double etc? Because it would only work for builtin >>>>> types, so what about types that aren't exposed to Python but can still >>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>> strings instead. I also think e.g. "int *" reads better than >>>>> cython.pointer(cython.int). >>>> >>>> That's whey we offer cython.p_int. On that note, we should support >>>> cython.astype("int *") or something like that. Generally, I don't like >>>> encoding semantic information in strings. >>>> >>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>> can't support both. Most of the time it should dispatch (at runtime or >>>> compile time) based on the type of the arguments. >>> >>> If we have an argument type that is composed of a fused type, would be >>> want the indexing to specify the composed type or the fused type? e.g. >>> >>> ctypedef floating *floating_p >> >> How should we support this? It's clear in this case, but only because >> you chose good names. Another option would be to require >> parameterization floating_p, with floating_p[floating] the >> "as-yet-unparameterized" version. Explicit but redundant. (The same >> applies to struct as classes as well as typedefs.) On the other had, >> the above is very succinct and clear in context, so I'm leaning >> towards it. Thoughts? > > Well, it is already supported. floating is fused, so any composition > of floating is also fused. > >>> cdef func(floating_p x): >>> ? ?... >>> >>> Then do we want >>> >>> ? ?func[double](10.0) >>> >>> or >>> >>> ? ?func[double_p](10.0) >>> >>> to specialize func? >> >> The latter. > > I'm really leaning towards the former. Ugh. I totally changed the meaning of that when I refactored my email. I'm in agreement with you: func[double]. > What if you write > > cdef func(floating_p x, floating_p *y): > ? ?... > > Then specializing floating_p using double_p sounds slightly > nonsensical, as you're also specializing floating_p *. > >>> FYI, the type checking works like 'double_p is >>> floating_p' and not 'double is floating_p'. But for functions this is >>> a little different. On the one hand specifying the full types >>> (double_p) makes sense as you're kind of specifying a signature, but >>> on the other hand you're specializing fused types and you don't care >>> how they are composed -- especially if they occur multiple times with >>> different composition. So I'm thinking we want 'func[double]'. >> >> That's what I'm thinking too. The type you're branching on is >> floating, and withing that block you can declare variables as >> floating*, ndarray[dtype=floating], etc. > > What I actually meant there was "I think we want func[double] for the > func(floating_p x) signature". > > Right, people can already say 'cdef func(floating *p): ...' and then > use 'floating'. However, if you do 'cdef floating_p x): ...', then > 'floating' is not available, only 'floating_p'. It would be rather > trivial to also support 'floating' in the latter case, which I think > we should, floating is implicitly available, we could require making it explicit. > unless you are adamant about prohibiting regular typedefs > of fused types. No, I'm nto adamant against it, just wanted to get some discussion going. - Robert From robertwb at math.washington.edu Tue May 3 18:23:51 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 3 May 2011 09:23:51 -0700 Subject: [Cython] Fused Types In-Reply-To: <4DC00BCD.7090508@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC00862.6030603@behnel.de> <4DC00BCD.7090508@astro.uio.no> Message-ID: On Tue, May 3, 2011 at 7:06 AM, Dag Sverre Seljebotn wrote: > On 05/03/2011 03:51 PM, Stefan Behnel wrote: >> >> mark florisson, 03.05.2011 15:17: >>> >>> if you have >>> >>> cdef func(floating x, floating y): >>> ... >>> >>> you get a "float, float" version, and a "double, double" version, but >>> not "float, double" or "double, float". >> >> So, what would you have to do in order to get a "float, double" and >> "double, float" version then? Could you get that with >> >> ctypedef fused_type(double, float) floating_df >> ctypedef fused_type(float, double) floating_fd >> >> cdef func(floating_df x, floating_fd y): >> >> ? > > Well, if you do something like > > ctypedef fused_type(float, double) speed_t > ctypedef fused_type(float, double) acceleration_t > > cdef func(speed_t x, acceleration_t y) > > then you get 4 specializations. Each new typedef gives a new polymorphic > type. Yep. > OTOH, with > > ctypedef speed_t acceleration_t > > I guess only 2 specializations. > > Treating the typedefs in this way is slightly fishy of course. It may hint > that "ctypedef" is the wrong way to declare a fused type *shrug*. True, but if we start supporting nested things, I think this still makes the most sense. E.g. ctypedef floating speed_t ctypedef floating acceleration_t struct delta: speed_t v acceleration_t a would still be exactly two versions (or three, if we throw long-double in there), rather than having un-intended combinatorial explosion. The as-yet-unspecialized version of delta would be delta[floating] or, possibly, just delta. One could explicitly ask for delta[double] or delta[float]. In terms of floating_p, note that "floating is double" and "floating_p is double*" could both make perfect sense for that particular specialization. In terms of compiler support, as long as ctypedef double my_double produced something "in floating" then I think it could all be done in a header file. - Robert From markflorisson88 at gmail.com Tue May 3 19:04:16 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 19:04:16 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DC012EF.3030306@molden.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC00862.6030603@behnel.de> <4DC00BCD.7090508@astro.uio.no> <4DC012EF.3030306@molden.no> Message-ID: On 3 May 2011 16:36, Sturla Molden wrote: > Den 03.05.2011 16:06, skrev Dag Sverre Seljebotn: >> >> Well, if you do something like >> >> ctypedef fused_type(float, double) speed_t >> ctypedef fused_type(float, double) acceleration_t >> >> cdef func(speed_t x, acceleration_t y) >> >> then you get 4 specializations. Each new typedef gives a new polymorphic >> type. >> >> OTOH, with >> >> ctypedef speed_t acceleration_t >> >> I guess only 2 specializations. >> >> Treating the typedefs in this way is slightly fishy of course. It may hint >> that "ctypedef" is the wrong way to declare a fused type *shrug*. >> >> To only get the "cross-versions" you'd need something like what you wrote >> + Pauli's "paired"-suggestion. >> > > This is a bloatware generator. > > It might not be used right, or it might generate bloat due to small mistakes > (which will go unnoticed/silent). Except that we could decide to not generate code for unused specializations. In any case, the C compile will know it, and issue warnings if we don't, as the functions are static. > > Sturla > > > > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From markflorisson88 at gmail.com Tue May 3 19:06:09 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 3 May 2011 19:06:09 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBBBF78.4030104@astro.uio.no> Message-ID: On 3 May 2011 18:00, Robert Bradshaw wrote: > On Tue, May 3, 2011 at 12:59 AM, mark florisson > wrote: >> On 3 May 2011 00:21, Robert Bradshaw wrote: >>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>> wrote: >>>> On 2 May 2011 18:24, Robert Bradshaw wrote: >>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>> wrote: >>>>>> A remaining issue which I'm not quite certain about is the >>>>>> specialization through subscripts, e.g. func[double]. How should this >>>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>> types, so what about types that aren't exposed to Python but can still >>>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>> cython.pointer(cython.int). >>>>> >>>>> That's whey we offer cython.p_int. On that note, we should support >>>>> cython.astype("int *") or something like that. Generally, I don't like >>>>> encoding semantic information in strings. >>>>> >>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>> can't support both. Most of the time it should dispatch (at runtime or >>>>> compile time) based on the type of the arguments. >>>> >>>> If we have an argument type that is composed of a fused type, would be >>>> want the indexing to specify the composed type or the fused type? e.g. >>>> >>>> ctypedef floating *floating_p >>> >>> How should we support this? It's clear in this case, but only because >>> you chose good names. Another option would be to require >>> parameterization floating_p, with floating_p[floating] the >>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>> applies to struct as classes as well as typedefs.) On the other had, >>> the above is very succinct and clear in context, so I'm leaning >>> towards it. Thoughts? >> >> Well, it is already supported. floating is fused, so any composition >> of floating is also fused. >> >>>> cdef func(floating_p x): >>>> ? ?... >>>> >>>> Then do we want >>>> >>>> ? ?func[double](10.0) >>>> >>>> or >>>> >>>> ? ?func[double_p](10.0) >>>> >>>> to specialize func? >>> >>> The latter. >> >> I'm really leaning towards the former. > > Ugh. I totally changed the meaning of that when I refactored my email. > I'm in agreement with you: func[double]. I see, however Dag just agreed on double_p :) So it depends, as Dag said, we can view ctypedef floating *floating_p as a fused type with variable part double * and float *. But you can also view the variable part as double and float. Either way makes sense, but the former allows you to differentiate floating from floating_p. So I suppose that if we want func[double] to specialize 'cdef func(floating_p x, floating y)', then it would specialize both floating_p and floating. However, if we settle on Dag's proposal, we can differentiate 'floating' from 'floating_p' and we could make 'speed_t' and 'acceleration_t' a ctypedef of floating. So I guess Dag's proposal makes sense, because if you want a single specialization, you'd write 'cdef func(floating *x, floating y)'. So overall you get more flexibility. >> What if you write >> >> cdef func(floating_p x, floating_p *y): >> ? ?... >> >> Then specializing floating_p using double_p sounds slightly >> nonsensical, as you're also specializing floating_p *. >> >>>> FYI, the type checking works like 'double_p is >>>> floating_p' and not 'double is floating_p'. But for functions this is >>>> a little different. On the one hand specifying the full types >>>> (double_p) makes sense as you're kind of specifying a signature, but >>>> on the other hand you're specializing fused types and you don't care >>>> how they are composed -- especially if they occur multiple times with >>>> different composition. So I'm thinking we want 'func[double]'. >>> >>> That's what I'm thinking too. The type you're branching on is >>> floating, and withing that block you can declare variables as >>> floating*, ndarray[dtype=floating], etc. >> >> What I actually meant there was "I think we want func[double] for the >> func(floating_p x) signature". >> >> Right, people can already say 'cdef func(floating *p): ...' and then >> use 'floating'. However, if you do 'cdef floating_p x): ...', then >> 'floating' is not available, only 'floating_p'. It would be rather >> trivial to also support 'floating' in the latter case, which I think >> we should, > > floating is implicitly available, we could require making it explicit. How would we make it explicit. >> unless you are adamant about prohibiting regular typedefs >> of fused types. > > No, I'm nto adamant against it, just wanted to get some discussion going. > > - Robert > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Tue May 3 19:52:45 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 03 May 2011 19:52:45 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DBBBF78.4030104@astro.uio.no> Message-ID: <9295a5f1-1c52-43f1-9ae9-6643f7bf92e1@email.android.com> I was wrong. We need cdef f(floating x, floating_p y) ...to get 2 specializations, not 4. And the rest follows from there. So I'm with Robert's real stance :-) I don't think we want flexibility, we want simplicity over all. You can always use a templating language. Btw we shouldn't count on pruning for the design of this, I think this will for a large part be used with def functions. And if you use a cdef function from another module through a pxd, you also need all versions. DS -- Sent from my Android phone with K-9 Mail. Please excuse my brevity. mark florisson wrote: On 3 May 2011 18:00, Robert Bradshaw wrote: > On Tue, May 3, 2011 at 12:59 AM, mark florisson > wrote: >> On 3 May 2011 00:21, Robert Bradshaw wrote: >>> On Mon, May 2, 2011 at 1:56 PM, mark florisson >>> wrote: >>>> On 2 May 2011 18:24, Robert Bradshaw wrote: >>>>> On Sun, May 1, 2011 at 2:38 AM, mark florisson >>>>> wrote: >>>>>> A remaining issue which I'm not quite certain about is the >>>>>> specialization through subscripts, e.g. func[double]. How should this >>>>>> work from Python space (assuming cpdef functions)? Would we want to >>>>>> pass in cython.double etc? Because it would only work for builtin >>>>>> types, so what about types that aren't exposed to Python but can still >>>>>> be coerced to and from Python? Perhaps it would be better to pass in >>>>>> strings instead. I also think e.g. "int *" reads better than >>>>>> cython.pointer(cython.int). >>>>> >>>>> That's whey we offer cython.p_int. On that note, we should support >>>>> cython.astype("int *") or something like that. Generally, I don't like >>>>> encoding semantic information in strings. >>>>> >>>>> OTHO, since it'll be a mapping of some sort, there's no reason we >>>>> can't support both. Most of the time it should dispatch (at runtime or >>>>> compile time) based on the type of the arguments. >>>> >>>> If we have an argument type that is composed of a fused type, would be >>>> want the indexing to specify the composed type or the fused type? e.g. >>>> >>>> ctypedef floating *floating_p >>> >>> How should we support this? It's clear in this case, but only because >>> you chose good names. Another option would be to require >>> parameterization floating_p, with floating_p[floating] the >>> "as-yet-unparameterized" version. Explicit but redundant. (The same >>> applies to struct as classes as well as typedefs.) On the other had, >>> the above is very succinct and clear in context, so I'm leaning >>> towards it. Thoughts? >> >> Well, it is already supported. floating is fused, so any composition >> of floating is also fused. >> >>>> cdef func(floating_p x): >>>> ... >>>> >>>> Then do we want >>>> >>>> func[double](10.0) >>>> >>>> or >>>> >>>> func[double_p](10.0) >>>> >>>> to specialize func? >>> >>> The latter. >> >> I'm really leaning towards the former. > > Ugh. I totally changed the meaning of that when I refactored my email. > I'm in agreement with you: func[double]. I see, however Dag just agreed on double_p :) So it depends, as Dag said, we can view ctypedef floating *floating_p as a fused type with variable part double * and float *. But you can also view the variable part as double and float. Either way makes sense, but the former allows you to differentiate floating from floating_p. So I suppose that if we want func[double] to specialize 'cdef func(floating_p x, floating y)', then it would specialize both floating_p and floating. However, if we settle on Dag's proposal, we can differentiate 'floating' from 'floating_p' and we could make 'speed_t' and 'acceleration_t' a ctypedef of floating. So I guess Dag's proposal makes sense, because if you want a single specialization, you'd write 'cdef func(floating *x, floating y)'. So overall you get more flexibility. >> What if you write >> >> cdef func(floating_p x, floating_p *y): >> ... >> >> Then specializing floating_p using double_p sounds slightly >> nonsensical, as you're also specializing floating_p *. >> >>>> FYI, the type checking works like 'double_p is >>>> floating_p' and not 'double is floating_p'. But for functions this is >>>> a little different. On the one hand specifying the full types >>>> (double_p) makes sense as you're kind of specifying a signature, but >>>> on the other hand you're specializing fused types and you don't care >>>> how they are composed -- especially if they occur multiple times with >>>> different composition. So I'm thinking we want 'func[double]'. >>> >>> That's what I'm thinking too. The type you're branching on is >>> floating, and withing that block you can declare variables as >>> floating*, ndarray[dtype=floating], etc. >> >> What I actually meant there was "I think we want func[double] for the >> func(floating_p x) signature". >> >> Right, people can already say 'cdef func(floating *p): ...' and then >> use 'floating'. However, if you do 'cdef floating_p x): ...', then >> 'floating' is not available, only 'floating_p'. It would be rather >> trivial to also support 'floating' in the latter case, which I think >> we should, > > floating is implicitly available, we could require making it explicit. How would we make it explicit. >> unless you are adamant about prohibiting regular typedefs >> of fused types. > > No, I'm nto adamant against it, just wanted to get some discussion going. > > - Robert >_____________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel >_____________________________________________ cython-devel mailing list cython-devel at python.org http://mail.python.org/mailman/listinfo/cython-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From robertwb at math.washington.edu Tue May 3 20:19:10 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 3 May 2011 11:19:10 -0700 Subject: [Cython] Fused Types In-Reply-To: <9295a5f1-1c52-43f1-9ae9-6643f7bf92e1@email.android.com> References: <4DBBBF78.4030104@astro.uio.no> <9295a5f1-1c52-43f1-9ae9-6643f7bf92e1@email.android.com> Message-ID: On Tue, May 3, 2011 at 10:06 AM, mark florisson wrote: > On 3 May 2011 18:00, Robert Bradshaw wrote: >> floating is implicitly available, we could require making it explicit. > > How would we make it explicit. Require the parameterization, i.e. floating_p[floating] would be the as-yet-unspecified type. In this particular example, it does seem unnecessarily verbose. Without it, one would have to know that cdef object foo(Vector v): ... may depend on floating if Vector does. On Tue, May 3, 2011 at 10:52 AM, Dag Sverre Seljebotn wrote: > I was wrong. We need > > cdef f(floating x, floating_p y) > > ...to get 2 specializations, not 4. And the rest follows from there. So I'm > with Robert's real stance :-) > > I don't think we want flexibility, we want simplicity over all. You can > always use a templating language. +1 > Btw we shouldn't count on pruning for the design of this, I think this will > for a large part be used with def functions. And if you use a cdef function > from another module through a pxd, you also need all versions. Well, we'll want to avoid compiler warnings. E.g. floating might include long double, but only float and double may be used. In pxd and def functions, however, we will make all versions available. - Robert From d.s.seljebotn at astro.uio.no Tue May 3 21:59:36 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 03 May 2011 21:59:36 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DBBBF78.4030104@astro.uio.no> <9295a5f1-1c52-43f1-9ae9-6643f7bf92e1@email.android.com> Message-ID: <4DC05EA8.9000202@astro.uio.no> On 05/03/2011 08:19 PM, Robert Bradshaw wrote: >> Btw we shouldn't count on pruning for the design of this, I think this will >> for a large part be used with def functions. And if you use a cdef function >> from another module through a pxd, you also need all versions. > > Well, we'll want to avoid compiler warnings. E.g. floating might > include long double, but only float and double may be used. In pxd and > def functions, however, we will make all versions available. Which is a reminder to hash out exactly how the dispatch will be resolved when coming from Python space (we do want to support "f(x, y)", without []-qualifier, when calling from Python, right?) Fused types mostly make sense when used through PEP 3118 memory views (using the planned syntax for brevity): def f(floating[:] x, floating y): ... I'm thinking that in this kind of situation we let the array override how y is interpreted (y will always be a double here, but if x is passed as a float32 then use float32 for y as well and coerce y). Does this make sense as a general rule -- if there's a conflict between array arguments and scalar arguments (array base type is narrower than the scalar type), the array argument wins? It makes sense because we can easily convert a scalar while we can't convert an array; and there's no "3.4f" notation in Python. This makes less sense def f(floating x): ... as it can only ever resolve to double; although I guess we should allow it for consistency with usecases that do make sense, such as "real_or_complex" and "int_or_float" The final and most difficult problem is what Python ints resolve to in this context. The widest integer type available in the fused type? Always Py_ssize_t? -1 on making the dispatch depend on the actual run-time value. Dag Sverre From greg.ewing at canterbury.ac.nz Wed May 4 01:07:03 2011 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Wed, 04 May 2011 11:07:03 +1200 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> Message-ID: <4DC08A97.5070009@canterbury.ac.nz> mark florisson wrote: > cdef func(floating x, floating y): > ... > > you get a "float, float" version, and a "double, double" version, but > not "float, double" or "double, float". It's hard to draw conclusions from this example because it's degenerate. You don't really need multiple versions of a function like that, because of float <-> double coercions. A more telling example might be cdef double dot_product(floating *u, floating *v, int length) By your current rules, this would give you one version that takes two float vectors, and another that takes two double vectors. But if you want to find the dot product of a float vector and a double vector, you're out of luck. -- Greg From greg.ewing at canterbury.ac.nz Wed May 4 01:40:17 2011 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Wed, 04 May 2011 11:40:17 +1200 Subject: [Cython] Fused Types In-Reply-To: <4DC00BCD.7090508@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC00862.6030603@behnel.de> <4DC00BCD.7090508@astro.uio.no> Message-ID: <4DC09261.5060308@canterbury.ac.nz> Dag Sverre Seljebotn wrote: > ctypedef fused_type(float, double) speed_t > ctypedef fused_type(float, double) acceleration_t > > then you get 4 specializations. > > ctypedef speed_t acceleration_t > > I guess only 2 specializations. > > Treating the typedefs in this way is slightly fishy of course. Indeed. This whole business seems rather too implicit to me. I think I'd rather have explicit type parameters in some form. Maybe cdef func2[floating F](F x, F y): # 2 specialisations cdef func4[floating F, floating G](F x, G y): # 4 specialisations This also makes it clear how to refer to particular specialisations: func2[float] or func4[float, double]. Pointers are handled in a natural way: cdef funcfp[floating F](F x, F *y): # 2 specialisations It also extends naturally to fused types used in other contexts: cdef struct Vector[floating F]: F x, y, z -- Greg From robertwb at math.washington.edu Wed May 4 02:52:40 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 3 May 2011 17:52:40 -0700 Subject: [Cython] Fused Types In-Reply-To: <4DC05EA8.9000202@astro.uio.no> References: <4DBBBF78.4030104@astro.uio.no> <9295a5f1-1c52-43f1-9ae9-6643f7bf92e1@email.android.com> <4DC05EA8.9000202@astro.uio.no> Message-ID: On Tue, May 3, 2011 at 12:59 PM, Dag Sverre Seljebotn wrote: > On 05/03/2011 08:19 PM, Robert Bradshaw wrote: > >>> Btw we shouldn't count on pruning for the design of this, I think this >>> will >>> for a large part be used with def functions. And if you use a cdef >>> function >>> from another module through a pxd, you also need all versions. >> >> Well, we'll want to avoid compiler warnings. E.g. floating might >> include long double, but only float and double may be used. In pxd and >> def functions, however, we will make all versions available. > > Which is a reminder to hash out exactly how the dispatch will be resolved > when coming from Python space (we do want to support "f(x, y)", without > []-qualifier, when calling from Python, right?) > > Fused types mostly make sense when used through PEP 3118 memory views (using > the planned syntax for brevity): > > def f(floating[:] x, floating y): ... > > I'm thinking that in this kind of situation we let the array override how y > is interpreted (y will always be a double here, but if x is passed as a > float32 then use float32 for y as well and coerce y). > > Does this make sense as a general rule -- if there's a conflict between > array arguments and scalar arguments (array base type is narrower than the > scalar type), the array argument wins? It makes sense because we can easily > convert a scalar while we can't convert an array; and there's no "3.4f" > notation in Python. I hadn't thought of that... it''s a bit odd, but we do have object -> float but no float[:] -> double[:], so the notion of something being the only match, even if it involves truncation, would be OK here. I'd like the rules to be clear. Perhaps we allow object -> float (e.g. in the auto-dispatching mode) but not double -> float. > This makes less sense > > def f(floating x): ... > > as it can only ever resolve to double; although I guess we should allow it > for consistency with usecases that do make sense, such as "real_or_complex" > and "int_or_float" > > The final and most difficult problem is what Python ints resolve to in this > context. The widest integer type available in the fused type? Always > Py_ssize_t? -1 on making the dispatch depend on the actual run-time value. -1 to run-time cutoffs. I'd choose the widest integral type. - Robert From robertwb at math.washington.edu Wed May 4 03:00:05 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 3 May 2011 18:00:05 -0700 Subject: [Cython] Fused Types In-Reply-To: <4DC09261.5060308@canterbury.ac.nz> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC00862.6030603@behnel.de> <4DC00BCD.7090508@astro.uio.no> <4DC09261.5060308@canterbury.ac.nz> Message-ID: On Tue, May 3, 2011 at 4:40 PM, Greg Ewing wrote: > Dag Sverre Seljebotn wrote: > >> ctypedef fused_type(float, double) speed_t >> ctypedef fused_type(float, double) acceleration_t >> >> then you get 4 specializations. >> >> ctypedef speed_t acceleration_t >> >> I guess only 2 specializations. >> >> Treating the typedefs in this way is slightly fishy of course. > > Indeed. This whole business seems rather too implicit to > me. I think I'd rather have explicit type parameters in > some form. Maybe > > ?cdef func2[floating F](F x, F y): > ? ?# 2 specialisations > > ?cdef func4[floating F, floating G](F x, G y): > ? ?# 4 specialisations > > This also makes it clear how to refer to particular > specialisations: func2[float] or func4[float, double]. > > Pointers are handled in a natural way: > > ?cdef funcfp[floating F](F x, F *y): > ? ?# 2 specialisations > > It also extends naturally to fused types used in other > contexts: > > ?cdef struct Vector[floating F]: > ? ?F x, y, z That's an idea, it is nice and explicit without being too verbose. Any thoughts on how one would define one's own "floating?" I presume one then use a Vector[F] inside of func2[floating F]? - Robert From vitja.makarov at gmail.com Wed May 4 07:09:18 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 4 May 2011 09:09:18 +0400 Subject: [Cython] jenkins problems Message-ID: Hi! Jenkins doesn't work for me. It seems that it can't do pull and is running tests again obsolete sources. May be because of forced push. There are only 6 errors here: https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ -- vitja. From vitja.makarov at gmail.com Wed May 4 07:50:22 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 4 May 2011 09:50:22 +0400 Subject: [Cython] jenkins problems In-Reply-To: References: Message-ID: 2011/5/4 Vitja Makarov : > Hi! > > Jenkins doesn't work for me. It seems that it can't do pull and is > running tests again obsolete sources. > May be because of forced push. > > There are only 6 errors here: > https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ > Can you please provide me jenkins account and I'll try to fix the issues myself? -- vitja. From vitja.makarov at gmail.com Wed May 4 08:35:18 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 4 May 2011 10:35:18 +0400 Subject: [Cython] jenkins problems In-Reply-To: References: Message-ID: 2011/5/4 Vitja Makarov : > 2011/5/4 Vitja Makarov : >> Hi! >> >> Jenkins doesn't work for me. It seems that it can't do pull and is >> running tests again obsolete sources. >> May be because of forced push. >> >> There are only 6 errors here: >> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ >> > > Can you please provide me jenkins account and I'll try to fix the issues myself? > It's better to use: $ git fetch origin $ git checkout -f origin/master Instead of git pull -- vitja. From markflorisson88 at gmail.com Wed May 4 09:26:53 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 09:26:53 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DC08A97.5070009@canterbury.ac.nz> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC08A97.5070009@canterbury.ac.nz> Message-ID: On 4 May 2011 01:07, Greg Ewing wrote: > mark florisson wrote: > >> cdef func(floating x, floating y): >> ? ?... >> >> you get a "float, float" version, and a "double, double" version, but >> not "float, double" or "double, float". > > It's hard to draw conclusions from this example because > it's degenerate. You don't really need multiple versions of a > function like that, because of float <-> double coercions. It's only degenerate if you want a real world example, and not one that provides a simple answer to your original question... > A more telling example might be > > ?cdef double dot_product(floating *u, floating *v, int length) > > By your current rules, this would give you one version that > takes two float vectors, and another that takes two double > vectors. > > But if you want to find the dot product of a float vector and > a double vector, you're out of luck. Sure, so you can create two fused types. I do however somewhat like your proposal with the indexing in the definition. > -- > Greg > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Wed May 4 10:24:47 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 10:24:47 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DC08A97.5070009@canterbury.ac.nz> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC08A97.5070009@canterbury.ac.nz> Message-ID: <4DC10D4F.8010209@astro.uio.no> On 05/04/2011 01:07 AM, Greg Ewing wrote: > mark florisson wrote: > >> cdef func(floating x, floating y): >> ... >> >> you get a "float, float" version, and a "double, double" version, but >> not "float, double" or "double, float". > > It's hard to draw conclusions from this example because > it's degenerate. You don't really need multiple versions of a > function like that, because of float <-> double coercions. > > A more telling example might be > > cdef double dot_product(floating *u, floating *v, int length) > > By your current rules, this would give you one version that > takes two float vectors, and another that takes two double > vectors. > > But if you want to find the dot product of a float vector and > a double vector, you're out of luck. First, I'm open for your proposed syntax too...But in the interest of seeing how we got here: The argument to the above goes that you *should* be out of luck. For instance, talking about dot products, BLAS itself has float-float and double-double, but not float-double AFAIK. What you are saying that this does not have the full power of C++ templates. And the answer is that yes, this does not have the full power of C++ templates. At the same time we discussed this, we also discussed better support for string-based templating languages (so that, e.g., compilation error messages could refer to the template file). The two are complementary. Going back to Greg's syntax: What I don't like is that it makes the simple unambiguous cases, where this would actually be used in real life, less readable. Would it be too complicated to have both? For instance; i) You are allowed to use a *single* fused_type on a *function* without declaration. def f(floating x, floating *y): # ok Turns into def f[floating T](T x, T *y): This is NOT ok: def f(floating x, integral y): # ERROR: Please explicitly declare fused types inside [] ii) Using more than one fused type, or using it on a cdef class or struct, you need to use the [] declaration. Finally: It is a bit uncomfortable that we seem to be hashing things out even as Mark is implementing this. Would it be feasible to have a Skype session sometimes this week where everybody interested in the outcome of this come together for an hour and actually decide on something? Mark: How much does this discussion of syntax impact your development? Are you able to treat them just as polish on top and work on the "engine" undisturbed by this? Dag Sverre From markflorisson88 at gmail.com Wed May 4 10:47:27 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 10:47:27 +0200 Subject: [Cython] Fused Types In-Reply-To: <4DC10D4F.8010209@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC08A97.5070009@canterbury.ac.nz> <4DC10D4F.8010209@astro.uio.no> Message-ID: On 4 May 2011 10:24, Dag Sverre Seljebotn wrote: > On 05/04/2011 01:07 AM, Greg Ewing wrote: >> >> mark florisson wrote: >> >>> cdef func(floating x, floating y): >>> ... >>> >>> you get a "float, float" version, and a "double, double" version, but >>> not "float, double" or "double, float". >> >> It's hard to draw conclusions from this example because >> it's degenerate. You don't really need multiple versions of a >> function like that, because of float <-> double coercions. >> >> A more telling example might be >> >> cdef double dot_product(floating *u, floating *v, int length) >> >> By your current rules, this would give you one version that >> takes two float vectors, and another that takes two double >> vectors. >> >> But if you want to find the dot product of a float vector and >> a double vector, you're out of luck. > > First, I'm open for your proposed syntax too...But in the interest of seeing > how we got here: > > The argument to the above goes that you *should* be out of luck. For > instance, talking about dot products, BLAS itself has float-float and > double-double, but not float-double AFAIK. > > What you are saying that this does not have the full power of C++ templates. > And the answer is that yes, this does not have the full power of C++ > templates. > > At the same time we discussed this, we also discussed better support for > string-based templating languages (so that, e.g., compilation error messages > could refer to the template file). The two are complementary. > > Going back to Greg's syntax: What I don't like is that it makes the simple > unambiguous cases, where this would actually be used in real life, less > readable. > > Would it be too complicated to have both? For instance; > > ?i) You are allowed to use a *single* fused_type on a *function* without > declaration. > > def f(floating x, floating *y): # ok > > Turns into > > def f[floating T](T x, T *y): > > This is NOT ok: > > def f(floating x, integral y): > # ERROR: Please explicitly declare fused types inside [] > > ?ii) Using more than one fused type, or using it on a cdef class or struct, > you need to use the [] declaration. > I don't think it would be too complicated, but as you mention it's probably not a very likely case, and if the user does need it, a new (equivalent) fused type can be created. The current way reads a lot nicer than the indexed one in my opinion. So I'd be fine with implementing it, but I find the current way more elegant. > Finally: It is a bit uncomfortable that we seem to be hashing things out > even as Mark is implementing this. Would it be feasible to have a Skype > session sometimes this week where everybody interested in the outcome of > this come together for an hour and actually decide on something? > > Mark: How much does this discussion of syntax impact your development? Are > you able to treat them just as polish on top and work on the "engine" > undisturbed by this? Thanks for your consideration, I admit it it feels a bit uncomfortable :) But at least this change shouldn't have such a big impact on the code, it would mean some changes in a select few places, so it's definitely polish. In any event, before we settle on this, I'd like to do the cpdef support first and work on indexing from Python space, so I think we have enough time to settle this argument on the ML. Before that, I'm just going to finish up for a pull request for the OpenMP branch, I'd like to see if I can get rid of some warnings. > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From markflorisson88 at gmail.com Wed May 4 12:00:20 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 12:00:20 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DB073BE.7010909@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> Message-ID: On 21 April 2011 20:13, Dag Sverre Seljebotn wrote: > On 04/21/2011 10:37 AM, Robert Bradshaw wrote: >> >> On Mon, Apr 18, 2011 at 7:51 AM, mark florisson >> ?wrote: >>> >>> On 18 April 2011 16:41, Dag Sverre Seljebotn >>> ?wrote: >>>> >>>> Excellent! Sounds great! (as I won't have my laptop for some days I >>>> can't >>>> have a look yet but I will later) >>>> >>>> You're right about (the current) buffers and the gil. A testcase >>>> explicitly >>>> for them would be good. >>>> >>>> Firstprivate etc: i think it'd be nice myself, but it is probably better >>>> to >>>> take a break from it at this point so that we can think more about that >>>> and >>>> not do anything rash; perhaps open up a specific thread on them and ask >>>> for >>>> more general input. Perhaps you want to take a break or task-switch to >>>> something else (fused types?) until I can get around to review and merge >>>> what you have so far? You'll know best what works for you though. If you >>>> decide to implement explicit threadprivate variables because you've got >>>> the >>>> flow I certainly wom't object myself. >>>> >>> ?Ok, cool, I'll move on :) I already included a test with a prange and >>> a numpy buffer with indexing. >> >> Wow, you're just plowing away at this. Very cool. >> >> +1 to disallowing nested prange, that seems to get really messy with >> little benefit. >> >> In terms of the CEP, I'm still unconvinced that firstprivate is not >> safe to infer, but lets leave the initial values undefined rather than >> specifying them to be NaNs (we can do that as an implementation if you >> want), which will give us flexibility to change later once we've had a >> chance to play around with it. > > I don't see any technical issues with inferring firstprivate, the question > is whether we want to. I suggest not inferring it in order to make this > safer: One should be able to just try to change a loop from "range" to > "prange", and either a) have things fail very hard, or b) just work > correctly and be able to trust the results. > > Note that when I suggest using NaN, it is as initial values for EACH > ITERATION, not per-thread initialization. It is not about "firstprivate" or > not, but about disabling thread-private variables entirely in favor of > "per-iteration" variables. > > I believe that by talking about "readonly" and "per-iteration" variables, > rather than "thread-shared" and "thread-private" variables, this can be used > much more safely and with virtually no knowledge of the details of > threading. Again, what's in my mind are scientific programmers with (too) > little training. > > In the end it's a matter of taste and what is most convenient to more users. > But I believe the case of needing real thread-private variables that > preserves per-thread values across iterations (and thus also can possibly > benefit from firstprivate) is seldomly enough used that an explicit > declaration is OK, in particular when it buys us so much in safety in the > common case. > > To be very precise, > > cdef double x, z > for i in prange(n): > ? ?x = f(x) > ? ?z = f(i) > ? ?... > > goes to > > cdef double x, z > for i in prange(n): > ? ?x = z = nan > ? ?x = f(x) > ? ?z = f(i) > ? ?... > > and we leave it to the C compiler to (trivially) optimize away "z = nan". > And, yes, it is a stopgap solution until we've got control flow analysis so > that we can outright disallow such uses of x (without threadprivate > declaration, which also gives firstprivate behaviour). > I think the preliminary OpenMP support is ready for review. It supports 'with cython.parallel.parallel:' and 'for i in cython.parallel.prange(...):'. It works in generators and closures and the docs are updated. Support for break/continue/with gil isn't there yet. There are two remaining issue. The first is warnings for potentially uninitialized variables for prange(). When you do for i in prange(start, stop, step): ... it generates code like nsteps = (stop - start) / step; #pragma omp parallel for lastprivate(i) for (temp = 0; temp < nsteps; temp++) { i = start + temp * step; ... } So here it will complain about 'i' being potentially uninitialized, as it might not be assigned to in the loop. However, simply assigning 0 to 'i' can't work either, as you expect zero iterations not to touch it. So for now, we have a bunch of warnings, as I don't see a __attribute__ to suppress it selectively. The second is NaN-ing private variables, NaN isn't part of C. For gcc, the docs ( http://www.delorie.com/gnu/docs/glibc/libc_407.html ) have the following to say: "You can use `#ifdef NAN' to test whether the machine supports NaN. (Of course, you must arrange for GNU extensions to be visible, such as by defining _GNU_SOURCE, and then you must include `math.h'.)" So I'm thinking that if NaN is not available (or the compiler is not GCC), we can use FLT_MAX, DBL_MAX and LDBL_MAX instead from float.h. Would this be the proper way to handle this? From d.s.seljebotn at astro.uio.no Wed May 4 12:45:49 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 12:45:49 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> Message-ID: <4DC12E5D.8050508@astro.uio.no> On 05/04/2011 12:00 PM, mark florisson wrote: > On 21 April 2011 20:13, Dag Sverre Seljebotn wrote: >> On 04/21/2011 10:37 AM, Robert Bradshaw wrote: >>> >>> On Mon, Apr 18, 2011 at 7:51 AM, mark florisson >>> wrote: >>>> >>>> On 18 April 2011 16:41, Dag Sverre Seljebotn >>>> wrote: >>>>> >>>>> Excellent! Sounds great! (as I won't have my laptop for some days I >>>>> can't >>>>> have a look yet but I will later) >>>>> >>>>> You're right about (the current) buffers and the gil. A testcase >>>>> explicitly >>>>> for them would be good. >>>>> >>>>> Firstprivate etc: i think it'd be nice myself, but it is probably better >>>>> to >>>>> take a break from it at this point so that we can think more about that >>>>> and >>>>> not do anything rash; perhaps open up a specific thread on them and ask >>>>> for >>>>> more general input. Perhaps you want to take a break or task-switch to >>>>> something else (fused types?) until I can get around to review and merge >>>>> what you have so far? You'll know best what works for you though. If you >>>>> decide to implement explicit threadprivate variables because you've got >>>>> the >>>>> flow I certainly wom't object myself. >>>>> >>>> Ok, cool, I'll move on :) I already included a test with a prange and >>>> a numpy buffer with indexing. >>> >>> Wow, you're just plowing away at this. Very cool. >>> >>> +1 to disallowing nested prange, that seems to get really messy with >>> little benefit. >>> >>> In terms of the CEP, I'm still unconvinced that firstprivate is not >>> safe to infer, but lets leave the initial values undefined rather than >>> specifying them to be NaNs (we can do that as an implementation if you >>> want), which will give us flexibility to change later once we've had a >>> chance to play around with it. >> >> I don't see any technical issues with inferring firstprivate, the question >> is whether we want to. I suggest not inferring it in order to make this >> safer: One should be able to just try to change a loop from "range" to >> "prange", and either a) have things fail very hard, or b) just work >> correctly and be able to trust the results. >> >> Note that when I suggest using NaN, it is as initial values for EACH >> ITERATION, not per-thread initialization. It is not about "firstprivate" or >> not, but about disabling thread-private variables entirely in favor of >> "per-iteration" variables. >> >> I believe that by talking about "readonly" and "per-iteration" variables, >> rather than "thread-shared" and "thread-private" variables, this can be used >> much more safely and with virtually no knowledge of the details of >> threading. Again, what's in my mind are scientific programmers with (too) >> little training. >> >> In the end it's a matter of taste and what is most convenient to more users. >> But I believe the case of needing real thread-private variables that >> preserves per-thread values across iterations (and thus also can possibly >> benefit from firstprivate) is seldomly enough used that an explicit >> declaration is OK, in particular when it buys us so much in safety in the >> common case. >> >> To be very precise, >> >> cdef double x, z >> for i in prange(n): >> x = f(x) >> z = f(i) >> ... >> >> goes to >> >> cdef double x, z >> for i in prange(n): >> x = z = nan >> x = f(x) >> z = f(i) >> ... >> >> and we leave it to the C compiler to (trivially) optimize away "z = nan". >> And, yes, it is a stopgap solution until we've got control flow analysis so >> that we can outright disallow such uses of x (without threadprivate >> declaration, which also gives firstprivate behaviour). >> > > I think the preliminary OpenMP support is ready for review. It > supports 'with cython.parallel.parallel:' and 'for i in > cython.parallel.prange(...):'. It works in generators and closures and > the docs are updated. Support for break/continue/with gil isn't there > yet. > > There are two remaining issue. The first is warnings for potentially > uninitialized variables for prange(). When you do > > for i in prange(start, stop, step): ... > > it generates code like > > nsteps = (stop - start) / step; > #pragma omp parallel for lastprivate(i) > for (temp = 0; temp< nsteps; temp++) { > i = start + temp * step; > ... > } > > So here it will complain about 'i' being potentially uninitialized, as > it might not be assigned to in the loop. However, simply assigning 0 > to 'i' can't work either, as you expect zero iterations not to touch > it. So for now, we have a bunch of warnings, as I don't see a > __attribute__ to suppress it selectively. Isn't this is orthogonal to OpenMP -- even if it said "range", your testcase could get such a warning? If so, the fix is simply to initialize i in your testcase code. > The second is NaN-ing private variables, NaN isn't part of C. For gcc, > the docs ( http://www.delorie.com/gnu/docs/glibc/libc_407.html ) have > the following to say: > > "You can use `#ifdef NAN' to test whether the machine supports NaN. > (Of course, you must arrange for GNU extensions to be visible, such as > by defining _GNU_SOURCE, and then you must include `math.h'.)" > > So I'm thinking that if NaN is not available (or the compiler is not > GCC), we can use FLT_MAX, DBL_MAX and LDBL_MAX instead from float.h. > Would this be the proper way to handle this? I think it is sufficient. A relatively portable way would be to initialize a double variable to 0.0/0.0 at program startup; a problem is that that would flag exceptions in the FPU though. Here's some more compiler-specific stuff I found: http://www.koders.com/c/fid6EF58B6683BCD810AE371607818952EB039CBC32.aspx DS From markflorisson88 at gmail.com Wed May 4 12:59:01 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 12:59:01 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC12E5D.8050508@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> Message-ID: On 4 May 2011 12:45, Dag Sverre Seljebotn wrote: > On 05/04/2011 12:00 PM, mark florisson wrote: >> >> On 21 April 2011 20:13, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 04/21/2011 10:37 AM, Robert Bradshaw wrote: >>>> >>>> On Mon, Apr 18, 2011 at 7:51 AM, mark florisson >>>> ? ?wrote: >>>>> >>>>> On 18 April 2011 16:41, Dag Sverre >>>>> Seljebotn >>>>> ?wrote: >>>>>> >>>>>> Excellent! Sounds great! (as I won't have my laptop for some days I >>>>>> can't >>>>>> have a look yet but I will later) >>>>>> >>>>>> You're right about (the current) buffers and the gil. A testcase >>>>>> explicitly >>>>>> for them would be good. >>>>>> >>>>>> Firstprivate etc: i think it'd be nice myself, but it is probably >>>>>> better >>>>>> to >>>>>> take a break from it at this point so that we can think more about >>>>>> that >>>>>> and >>>>>> not do anything rash; perhaps open up a specific thread on them and >>>>>> ask >>>>>> for >>>>>> more general input. Perhaps you want to take a break or task-switch to >>>>>> something else (fused types?) until I can get around to review and >>>>>> merge >>>>>> what you have so far? You'll know best what works for you though. If >>>>>> you >>>>>> decide to implement explicit threadprivate variables because you've >>>>>> got >>>>>> the >>>>>> flow I certainly wom't object myself. >>>>>> >>>>> ?Ok, cool, I'll move on :) I already included a test with a prange and >>>>> a numpy buffer with indexing. >>>> >>>> Wow, you're just plowing away at this. Very cool. >>>> >>>> +1 to disallowing nested prange, that seems to get really messy with >>>> little benefit. >>>> >>>> In terms of the CEP, I'm still unconvinced that firstprivate is not >>>> safe to infer, but lets leave the initial values undefined rather than >>>> specifying them to be NaNs (we can do that as an implementation if you >>>> want), which will give us flexibility to change later once we've had a >>>> chance to play around with it. >>> >>> I don't see any technical issues with inferring firstprivate, the >>> question >>> is whether we want to. I suggest not inferring it in order to make this >>> safer: One should be able to just try to change a loop from "range" to >>> "prange", and either a) have things fail very hard, or b) just work >>> correctly and be able to trust the results. >>> >>> Note that when I suggest using NaN, it is as initial values for EACH >>> ITERATION, not per-thread initialization. It is not about "firstprivate" >>> or >>> not, but about disabling thread-private variables entirely in favor of >>> "per-iteration" variables. >>> >>> I believe that by talking about "readonly" and "per-iteration" variables, >>> rather than "thread-shared" and "thread-private" variables, this can be >>> used >>> much more safely and with virtually no knowledge of the details of >>> threading. Again, what's in my mind are scientific programmers with (too) >>> little training. >>> >>> In the end it's a matter of taste and what is most convenient to more >>> users. >>> But I believe the case of needing real thread-private variables that >>> preserves per-thread values across iterations (and thus also can possibly >>> benefit from firstprivate) is seldomly enough used that an explicit >>> declaration is OK, in particular when it buys us so much in safety in the >>> common case. >>> >>> To be very precise, >>> >>> cdef double x, z >>> for i in prange(n): >>> ? ?x = f(x) >>> ? ?z = f(i) >>> ? ?... >>> >>> goes to >>> >>> cdef double x, z >>> for i in prange(n): >>> ? ?x = z = nan >>> ? ?x = f(x) >>> ? ?z = f(i) >>> ? ?... >>> >>> and we leave it to the C compiler to (trivially) optimize away "z = nan". >>> And, yes, it is a stopgap solution until we've got control flow analysis >>> so >>> that we can outright disallow such uses of x (without threadprivate >>> declaration, which also gives firstprivate behaviour). >>> >> >> I think the preliminary OpenMP support is ready for review. It >> supports 'with cython.parallel.parallel:' and 'for i in >> cython.parallel.prange(...):'. It works in generators and closures and >> the docs are updated. Support for break/continue/with gil isn't there >> yet. >> >> There are two remaining issue. The first is warnings for potentially >> uninitialized variables for prange(). When you do >> >> for i in prange(start, stop, step): ... >> >> it generates code like >> >> nsteps = (stop - start) / step; >> #pragma omp parallel for lastprivate(i) >> for (temp = 0; temp< ?nsteps; temp++) { >> ? ? i = start + temp * step; >> ? ? ... >> } >> >> So here it will complain about 'i' being potentially uninitialized, as >> it might not be assigned to in the loop. However, simply assigning 0 >> to 'i' can't work either, as you expect zero iterations not to touch >> it. So for now, we have a bunch of warnings, as I don't see a >> __attribute__ to suppress it selectively. > > Isn't this is orthogonal to OpenMP -- even if it said "range", your testcase > could get such a warning? If so, the fix is simply to initialize i in your > testcase code. No, the problem is that 'i' needs to be lastprivate, and 'i' is assigned to in the loop body. It's irrelevant whether 'i' is assigned to before the loop. I think this is the case because the spec says that lastprivate variables will get the value of the private variable of the last sequential iteration, but it cannot at compile time know whether there might be zero iterations, which I believe the spec doesn't have anything to say about. So basically we could guard against it by checking if nsteps > 0, but the compiler doesn't detect this, so it will still issue a warning even if 'i' is initialized (the warning is at the place of the lastprivate declaration). >> The second is NaN-ing private variables, NaN isn't part of C. For gcc, >> the docs ( http://www.delorie.com/gnu/docs/glibc/libc_407.html ) have >> the following to say: >> >> "You can use `#ifdef NAN' to test whether the machine supports NaN. >> (Of course, you must arrange for GNU extensions to be visible, such as >> by defining _GNU_SOURCE, and then you must include `math.h'.)" >> >> So I'm thinking that if NaN is not available (or the compiler is not >> GCC), we can use FLT_MAX, DBL_MAX and LDBL_MAX instead from float.h. >> Would this be the proper way to handle this? > > I think it is sufficient. A relatively portable way would be to initialize a > double variable to 0.0/0.0 at program startup; a problem is that that would > flag exceptions in the FPU though. > > Here's some more compiler-specific stuff I found: > > http://www.koders.com/c/fid6EF58B6683BCD810AE371607818952EB039CBC32.aspx Thanks, I'll take a look! > DS > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Wed May 4 13:15:09 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 13:15:09 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> Message-ID: <4DC1353D.2010607@astro.uio.no> On 05/04/2011 12:59 PM, mark florisson wrote: > On 4 May 2011 12:45, Dag Sverre Seljebotn wrote: >> On 05/04/2011 12:00 PM, mark florisson wrote: >>> There are two remaining issue. The first is warnings for potentially >>> uninitialized variables for prange(). When you do >>> >>> for i in prange(start, stop, step): ... >>> >>> it generates code like >>> >>> nsteps = (stop - start) / step; >>> #pragma omp parallel for lastprivate(i) >>> for (temp = 0; temp< nsteps; temp++) { >>> i = start + temp * step; >>> ... >>> } >>> >>> So here it will complain about 'i' being potentially uninitialized, as >>> it might not be assigned to in the loop. However, simply assigning 0 >>> to 'i' can't work either, as you expect zero iterations not to touch >>> it. So for now, we have a bunch of warnings, as I don't see a >>> __attribute__ to suppress it selectively. >> >> Isn't this is orthogonal to OpenMP -- even if it said "range", your testcase >> could get such a warning? If so, the fix is simply to initialize i in your >> testcase code. > > No, the problem is that 'i' needs to be lastprivate, and 'i' is > assigned to in the loop body. It's irrelevant whether 'i' is assigned > to before the loop. I think this is the case because the spec says > that lastprivate variables will get the value of the private variable > of the last sequential iteration, but it cannot at compile time know > whether there might be zero iterations, which I believe the spec > doesn't have anything to say about. So basically we could guard > against it by checking if nsteps> 0, but the compiler doesn't detect > this, so it will still issue a warning even if 'i' is initialized (the > warning is at the place of the lastprivate declaration). Ah. But this is then more important than I initially thought it was. You are saying that this is the case: cdef int i = 0 with nogil: for i in prange(n): ... print i # garbage when n == 0? It would be in the interest of less semantic differences w.r.t. range to deal better with this case. Will it silence the warning if we make "i" firstprivate as well as lastprivate? firstprivate would only affect the case of zero iterations, since we overwrite with NaN if the loop is entered... Dag From markflorisson88 at gmail.com Wed May 4 13:30:04 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 13:30:04 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC1353D.2010607@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> Message-ID: On 4 May 2011 13:15, Dag Sverre Seljebotn wrote: > On 05/04/2011 12:59 PM, mark florisson wrote: >> >> On 4 May 2011 12:45, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/04/2011 12:00 PM, mark florisson wrote: >>>> >>>> There are two remaining issue. The first is warnings for potentially >>>> uninitialized variables for prange(). When you do >>>> >>>> for i in prange(start, stop, step): ... >>>> >>>> it generates code like >>>> >>>> nsteps = (stop - start) / step; >>>> #pragma omp parallel for lastprivate(i) >>>> for (temp = 0; temp< ? ?nsteps; temp++) { >>>> ? ? i = start + temp * step; >>>> ? ? ... >>>> } >>>> >>>> So here it will complain about 'i' being potentially uninitialized, as >>>> it might not be assigned to in the loop. However, simply assigning 0 >>>> to 'i' can't work either, as you expect zero iterations not to touch >>>> it. So for now, we have a bunch of warnings, as I don't see a >>>> __attribute__ to suppress it selectively. >>> >>> Isn't this is orthogonal to OpenMP -- even if it said "range", your >>> testcase >>> could get such a warning? If so, the fix is simply to initialize i in >>> your >>> testcase code. >> >> No, the problem is that 'i' needs to be lastprivate, and 'i' is >> assigned to in the loop body. It's irrelevant whether 'i' is assigned >> to before the loop. I think this is the case because the spec says >> that lastprivate variables will get the value of the private variable >> of the last sequential iteration, but it cannot at compile time know >> whether there might be zero iterations, which I believe the spec >> doesn't have anything to say about. So basically we could guard >> against it by checking if nsteps> ?0, but the compiler doesn't detect >> this, so it will still issue a warning even if 'i' is initialized (the >> warning is at the place of the lastprivate declaration). > > Ah. But this is then more important than I initially thought it was. You are > saying that this is the case: > > cdef int i = 0 > with nogil: > ? ?for i in prange(n): > ? ? ? ?... > print i # garbage when n == 0? I think it may be, depending on the implementation. With libgomp it return 0. With the check it should also return 0. > It would be in the interest of less semantic differences w.r.t. range to > deal better with this case. > > Will it silence the warning if we make "i" firstprivate as well as > lastprivate? firstprivate would only affect the case of zero iterations, > since we overwrite with NaN if the loop is entered... Well, it wouldn't be NaN, it would be start + step * temp :) But, yes, that works. So we need both the check and an initialization in there: if (nsteps > 0) { i = 0; #pragma omp parallel for firstprivate(i) lastprivate(i) for (temp = 0; ...; ...) ... } Now any subsequent read of 'i' will only issue a warning if 'i' is not initialized before the prange() by the user. So if you leave your index variable uninitialized (because you know in advance nsteps will be greater than zero), you'll still get a warning. But at least you will be able to shut up the compiler :) > Dag > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Wed May 4 13:39:20 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 13:39:20 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> Message-ID: <4DC13AE8.6010604@astro.uio.no> On 05/04/2011 01:30 PM, mark florisson wrote: > On 4 May 2011 13:15, Dag Sverre Seljebotn wrote: >> On 05/04/2011 12:59 PM, mark florisson wrote: >>> >>> On 4 May 2011 12:45, Dag Sverre Seljebotn >>> wrote: >>>> >>>> On 05/04/2011 12:00 PM, mark florisson wrote: >>>>> >>>>> There are two remaining issue. The first is warnings for potentially >>>>> uninitialized variables for prange(). When you do >>>>> >>>>> for i in prange(start, stop, step): ... >>>>> >>>>> it generates code like >>>>> >>>>> nsteps = (stop - start) / step; >>>>> #pragma omp parallel for lastprivate(i) >>>>> for (temp = 0; temp< nsteps; temp++) { >>>>> i = start + temp * step; >>>>> ... >>>>> } >>>>> >>>>> So here it will complain about 'i' being potentially uninitialized, as >>>>> it might not be assigned to in the loop. However, simply assigning 0 >>>>> to 'i' can't work either, as you expect zero iterations not to touch >>>>> it. So for now, we have a bunch of warnings, as I don't see a >>>>> __attribute__ to suppress it selectively. >>>> >>>> Isn't this is orthogonal to OpenMP -- even if it said "range", your >>>> testcase >>>> could get such a warning? If so, the fix is simply to initialize i in >>>> your >>>> testcase code. >>> >>> No, the problem is that 'i' needs to be lastprivate, and 'i' is >>> assigned to in the loop body. It's irrelevant whether 'i' is assigned >>> to before the loop. I think this is the case because the spec says >>> that lastprivate variables will get the value of the private variable >>> of the last sequential iteration, but it cannot at compile time know >>> whether there might be zero iterations, which I believe the spec >>> doesn't have anything to say about. So basically we could guard >>> against it by checking if nsteps> 0, but the compiler doesn't detect >>> this, so it will still issue a warning even if 'i' is initialized (the >>> warning is at the place of the lastprivate declaration). >> >> Ah. But this is then more important than I initially thought it was. You are >> saying that this is the case: >> >> cdef int i = 0 >> with nogil: >> for i in prange(n): >> ... >> print i # garbage when n == 0? > > I think it may be, depending on the implementation. With libgomp it > return 0. With the check it should also return 0. > >> It would be in the interest of less semantic differences w.r.t. range to >> deal better with this case. >> >> Will it silence the warning if we make "i" firstprivate as well as >> lastprivate? firstprivate would only affect the case of zero iterations, >> since we overwrite with NaN if the loop is entered... > > Well, it wouldn't be NaN, it would be start + step * temp :) But, yes, Doh. > that works. So we need both the check and an initialization in there: > > if (nsteps> 0) { > i = 0; > #pragma omp parallel for firstprivate(i) lastprivate(i) > for (temp = 0; ...; ...) ... > } Why do you need the if-test? Won't simply #pragma omp parallel for firstprivate(i) lastprivate(i) for (temp = 0; ...; ...) ... do the job -- any initial value will be copied into all threads, including the "last" thread, even if there are no iterations? Dag Sverre From markflorisson88 at gmail.com Wed May 4 13:41:02 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 13:41:02 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC13AE8.6010604@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA60013.6060901@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> Message-ID: On 4 May 2011 13:39, Dag Sverre Seljebotn wrote: > On 05/04/2011 01:30 PM, mark florisson wrote: >> >> On 4 May 2011 13:15, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/04/2011 12:59 PM, mark florisson wrote: >>>> >>>> On 4 May 2011 12:45, Dag Sverre Seljebotn >>>> ?wrote: >>>>> >>>>> On 05/04/2011 12:00 PM, mark florisson wrote: >>>>>> >>>>>> There are two remaining issue. The first is warnings for potentially >>>>>> uninitialized variables for prange(). When you do >>>>>> >>>>>> for i in prange(start, stop, step): ... >>>>>> >>>>>> it generates code like >>>>>> >>>>>> nsteps = (stop - start) / step; >>>>>> #pragma omp parallel for lastprivate(i) >>>>>> for (temp = 0; temp< ? ? ?nsteps; temp++) { >>>>>> ? ? i = start + temp * step; >>>>>> ? ? ... >>>>>> } >>>>>> >>>>>> So here it will complain about 'i' being potentially uninitialized, as >>>>>> it might not be assigned to in the loop. However, simply assigning 0 >>>>>> to 'i' can't work either, as you expect zero iterations not to touch >>>>>> it. So for now, we have a bunch of warnings, as I don't see a >>>>>> __attribute__ to suppress it selectively. >>>>> >>>>> Isn't this is orthogonal to OpenMP -- even if it said "range", your >>>>> testcase >>>>> could get such a warning? If so, the fix is simply to initialize i in >>>>> your >>>>> testcase code. >>>> >>>> No, the problem is that 'i' needs to be lastprivate, and 'i' is >>>> assigned to in the loop body. It's irrelevant whether 'i' is assigned >>>> to before the loop. I think this is the case because the spec says >>>> that lastprivate variables will get the value of the private variable >>>> of the last sequential iteration, but it cannot at compile time know >>>> whether there might be zero iterations, which I believe the spec >>>> doesn't have anything to say about. So basically we could guard >>>> against it by checking if nsteps> ? ?0, but the compiler doesn't detect >>>> this, so it will still issue a warning even if 'i' is initialized (the >>>> warning is at the place of the lastprivate declaration). >>> >>> Ah. But this is then more important than I initially thought it was. You >>> are >>> saying that this is the case: >>> >>> cdef int i = 0 >>> with nogil: >>> ? ?for i in prange(n): >>> ? ? ? ?... >>> print i # garbage when n == 0? >> >> I think it may be, depending on the implementation. With libgomp it >> return 0. With the check it should also return 0. >> >>> It would be in the interest of less semantic differences w.r.t. range to >>> deal better with this case. >>> >>> Will it silence the warning if we make "i" firstprivate as well as >>> lastprivate? firstprivate would only affect the case of zero iterations, >>> since we overwrite with NaN if the loop is entered... >> >> Well, it wouldn't be NaN, it would be start + step * temp :) But, yes, > > Doh. > >> that works. So we need both the check and an initialization in there: >> >> if (nsteps> ?0) { >> ? ? i = 0; >> ? ? #pragma omp parallel for firstprivate(i) lastprivate(i) >> ? ? for (temp = 0; ...; ...) ... >> } > > Why do you need the if-test? Won't simply > > #pragma omp parallel for firstprivate(i) lastprivate(i) > for (temp = 0; ...; ...) ... > > do the job -- any initial value will be copied into all threads, including > the "last" thread, even if there are no iterations? It will, but you don't expect your iteration variable to change with zero iterations. > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Wed May 4 13:45:07 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 13:45:07 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> Message-ID: <4DC13C43.6050801@astro.uio.no> On 05/04/2011 01:41 PM, mark florisson wrote: > On 4 May 2011 13:39, Dag Sverre Seljebotn wrote: >> On 05/04/2011 01:30 PM, mark florisson wrote: >>> >>> On 4 May 2011 13:15, Dag Sverre Seljebotn >>> wrote: >>>> >>>> On 05/04/2011 12:59 PM, mark florisson wrote: >>>>> >>>>> On 4 May 2011 12:45, Dag Sverre Seljebotn >>>>> wrote: >>>>>> >>>>>> On 05/04/2011 12:00 PM, mark florisson wrote: >>>>>>> >>>>>>> There are two remaining issue. The first is warnings for potentially >>>>>>> uninitialized variables for prange(). When you do >>>>>>> >>>>>>> for i in prange(start, stop, step): ... >>>>>>> >>>>>>> it generates code like >>>>>>> >>>>>>> nsteps = (stop - start) / step; >>>>>>> #pragma omp parallel for lastprivate(i) >>>>>>> for (temp = 0; temp< nsteps; temp++) { >>>>>>> i = start + temp * step; >>>>>>> ... >>>>>>> } >>>>>>> >>>>>>> So here it will complain about 'i' being potentially uninitialized, as >>>>>>> it might not be assigned to in the loop. However, simply assigning 0 >>>>>>> to 'i' can't work either, as you expect zero iterations not to touch >>>>>>> it. So for now, we have a bunch of warnings, as I don't see a >>>>>>> __attribute__ to suppress it selectively. >>>>>> >>>>>> Isn't this is orthogonal to OpenMP -- even if it said "range", your >>>>>> testcase >>>>>> could get such a warning? If so, the fix is simply to initialize i in >>>>>> your >>>>>> testcase code. >>>>> >>>>> No, the problem is that 'i' needs to be lastprivate, and 'i' is >>>>> assigned to in the loop body. It's irrelevant whether 'i' is assigned >>>>> to before the loop. I think this is the case because the spec says >>>>> that lastprivate variables will get the value of the private variable >>>>> of the last sequential iteration, but it cannot at compile time know >>>>> whether there might be zero iterations, which I believe the spec >>>>> doesn't have anything to say about. So basically we could guard >>>>> against it by checking if nsteps> 0, but the compiler doesn't detect >>>>> this, so it will still issue a warning even if 'i' is initialized (the >>>>> warning is at the place of the lastprivate declaration). >>>> >>>> Ah. But this is then more important than I initially thought it was. You >>>> are >>>> saying that this is the case: >>>> >>>> cdef int i = 0 >>>> with nogil: >>>> for i in prange(n): >>>> ... >>>> print i # garbage when n == 0? >>> >>> I think it may be, depending on the implementation. With libgomp it >>> return 0. With the check it should also return 0. >>> >>>> It would be in the interest of less semantic differences w.r.t. range to >>>> deal better with this case. >>>> >>>> Will it silence the warning if we make "i" firstprivate as well as >>>> lastprivate? firstprivate would only affect the case of zero iterations, >>>> since we overwrite with NaN if the loop is entered... >>> >>> Well, it wouldn't be NaN, it would be start + step * temp :) But, yes, >> >> Doh. >> >>> that works. So we need both the check and an initialization in there: >>> >>> if (nsteps> 0) { >>> i = 0; >>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>> for (temp = 0; ...; ...) ... >>> } >> >> Why do you need the if-test? Won't simply >> >> #pragma omp parallel for firstprivate(i) lastprivate(i) >> for (temp = 0; ...; ...) ... >> >> do the job -- any initial value will be copied into all threads, including >> the "last" thread, even if there are no iterations? > > It will, but you don't expect your iteration variable to change with > zero iterations. Look. i = 42 for i in prange(n): f(i) print i # want 42 whenever n == 0 Now, translate this to: i = 42; #pragma omp parallel for firstprivate(i) lastprivate(i) for (temp = 0; ...; ...) { i = ... } #pragma omp parallel end /* At this point, i == 42 if n == 0 */ Am I missing something? DS From markflorisson88 at gmail.com Wed May 4 13:47:12 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 13:47:12 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC13C43.6050801@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> Message-ID: On 4 May 2011 13:45, Dag Sverre Seljebotn wrote: > On 05/04/2011 01:41 PM, mark florisson wrote: >> >> On 4 May 2011 13:39, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/04/2011 01:30 PM, mark florisson wrote: >>>> >>>> On 4 May 2011 13:15, Dag Sverre Seljebotn >>>> ?wrote: >>>>> >>>>> On 05/04/2011 12:59 PM, mark florisson wrote: >>>>>> >>>>>> On 4 May 2011 12:45, Dag Sverre Seljebotn >>>>>> ?wrote: >>>>>>> >>>>>>> On 05/04/2011 12:00 PM, mark florisson wrote: >>>>>>>> >>>>>>>> There are two remaining issue. The first is warnings for potentially >>>>>>>> uninitialized variables for prange(). When you do >>>>>>>> >>>>>>>> for i in prange(start, stop, step): ... >>>>>>>> >>>>>>>> it generates code like >>>>>>>> >>>>>>>> nsteps = (stop - start) / step; >>>>>>>> #pragma omp parallel for lastprivate(i) >>>>>>>> for (temp = 0; temp< ? ? ? ?nsteps; temp++) { >>>>>>>> ? ? i = start + temp * step; >>>>>>>> ? ? ... >>>>>>>> } >>>>>>>> >>>>>>>> So here it will complain about 'i' being potentially uninitialized, >>>>>>>> as >>>>>>>> it might not be assigned to in the loop. However, simply assigning 0 >>>>>>>> to 'i' can't work either, as you expect zero iterations not to touch >>>>>>>> it. So for now, we have a bunch of warnings, as I don't see a >>>>>>>> __attribute__ to suppress it selectively. >>>>>>> >>>>>>> Isn't this is orthogonal to OpenMP -- even if it said "range", your >>>>>>> testcase >>>>>>> could get such a warning? If so, the fix is simply to initialize i in >>>>>>> your >>>>>>> testcase code. >>>>>> >>>>>> No, the problem is that 'i' needs to be lastprivate, and 'i' is >>>>>> assigned to in the loop body. It's irrelevant whether 'i' is assigned >>>>>> to before the loop. I think this is the case because the spec says >>>>>> that lastprivate variables will get the value of the private variable >>>>>> of the last sequential iteration, but it cannot at compile time know >>>>>> whether there might be zero iterations, which I believe the spec >>>>>> doesn't have anything to say about. So basically we could guard >>>>>> against it by checking if nsteps> ? ? ?0, but the compiler doesn't >>>>>> detect >>>>>> this, so it will still issue a warning even if 'i' is initialized (the >>>>>> warning is at the place of the lastprivate declaration). >>>>> >>>>> Ah. But this is then more important than I initially thought it was. >>>>> You >>>>> are >>>>> saying that this is the case: >>>>> >>>>> cdef int i = 0 >>>>> with nogil: >>>>> ? ?for i in prange(n): >>>>> ? ? ? ?... >>>>> print i # garbage when n == 0? >>>> >>>> I think it may be, depending on the implementation. With libgomp it >>>> return 0. With the check it should also return 0. >>>> >>>>> It would be in the interest of less semantic differences w.r.t. range >>>>> to >>>>> deal better with this case. >>>>> >>>>> Will it silence the warning if we make "i" firstprivate as well as >>>>> lastprivate? firstprivate would only affect the case of zero >>>>> iterations, >>>>> since we overwrite with NaN if the loop is entered... >>>> >>>> Well, it wouldn't be NaN, it would be start + step * temp :) But, yes, >>> >>> Doh. >>> >>>> that works. So we need both the check and an initialization in there: >>>> >>>> if (nsteps> ? ?0) { >>>> ? ? i = 0; >>>> ? ? #pragma omp parallel for firstprivate(i) lastprivate(i) >>>> ? ? for (temp = 0; ...; ...) ... >>>> } >>> >>> Why do you need the if-test? Won't simply >>> >>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>> for (temp = 0; ...; ...) ... >>> >>> do the job -- any initial value will be copied into all threads, >>> including >>> the "last" thread, even if there are no iterations? >> >> It will, but you don't expect your iteration variable to change with >> zero iterations. > > Look. > > i = 42 > for i in prange(n): > ? ?f(i) > print i # want 42 whenever n == 0 > > Now, translate this to: > > i = 42; > #pragma omp parallel for firstprivate(i) lastprivate(i) > for (temp = 0; ...; ...) { > ? ?i = ... > } > #pragma omp parallel end > /* At this point, i == 42 if n == 0 */ > > Am I missing something? Yes, 'i' may be uninitialized with nsteps > 0 (this should be valid code). So if nsteps > 0, we need to initialize 'i' to something to get correct behaviour with firstprivate. From markflorisson88 at gmail.com Wed May 4 13:48:07 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 13:48:07 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA73D22.9050605@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> Message-ID: On 4 May 2011 13:47, mark florisson wrote: > On 4 May 2011 13:45, Dag Sverre Seljebotn wrote: >> On 05/04/2011 01:41 PM, mark florisson wrote: >>> >>> On 4 May 2011 13:39, Dag Sverre Seljebotn >>> ?wrote: >>>> >>>> On 05/04/2011 01:30 PM, mark florisson wrote: >>>>> >>>>> On 4 May 2011 13:15, Dag Sverre Seljebotn >>>>> ?wrote: >>>>>> >>>>>> On 05/04/2011 12:59 PM, mark florisson wrote: >>>>>>> >>>>>>> On 4 May 2011 12:45, Dag Sverre Seljebotn >>>>>>> ?wrote: >>>>>>>> >>>>>>>> On 05/04/2011 12:00 PM, mark florisson wrote: >>>>>>>>> >>>>>>>>> There are two remaining issue. The first is warnings for potentially >>>>>>>>> uninitialized variables for prange(). When you do >>>>>>>>> >>>>>>>>> for i in prange(start, stop, step): ... >>>>>>>>> >>>>>>>>> it generates code like >>>>>>>>> >>>>>>>>> nsteps = (stop - start) / step; >>>>>>>>> #pragma omp parallel for lastprivate(i) >>>>>>>>> for (temp = 0; temp< ? ? ? ?nsteps; temp++) { >>>>>>>>> ? ? i = start + temp * step; >>>>>>>>> ? ? ... >>>>>>>>> } >>>>>>>>> >>>>>>>>> So here it will complain about 'i' being potentially uninitialized, >>>>>>>>> as >>>>>>>>> it might not be assigned to in the loop. However, simply assigning 0 >>>>>>>>> to 'i' can't work either, as you expect zero iterations not to touch >>>>>>>>> it. So for now, we have a bunch of warnings, as I don't see a >>>>>>>>> __attribute__ to suppress it selectively. >>>>>>>> >>>>>>>> Isn't this is orthogonal to OpenMP -- even if it said "range", your >>>>>>>> testcase >>>>>>>> could get such a warning? If so, the fix is simply to initialize i in >>>>>>>> your >>>>>>>> testcase code. >>>>>>> >>>>>>> No, the problem is that 'i' needs to be lastprivate, and 'i' is >>>>>>> assigned to in the loop body. It's irrelevant whether 'i' is assigned >>>>>>> to before the loop. I think this is the case because the spec says >>>>>>> that lastprivate variables will get the value of the private variable >>>>>>> of the last sequential iteration, but it cannot at compile time know >>>>>>> whether there might be zero iterations, which I believe the spec >>>>>>> doesn't have anything to say about. So basically we could guard >>>>>>> against it by checking if nsteps> ? ? ?0, but the compiler doesn't >>>>>>> detect >>>>>>> this, so it will still issue a warning even if 'i' is initialized (the >>>>>>> warning is at the place of the lastprivate declaration). >>>>>> >>>>>> Ah. But this is then more important than I initially thought it was. >>>>>> You >>>>>> are >>>>>> saying that this is the case: >>>>>> >>>>>> cdef int i = 0 >>>>>> with nogil: >>>>>> ? ?for i in prange(n): >>>>>> ? ? ? ?... >>>>>> print i # garbage when n == 0? >>>>> >>>>> I think it may be, depending on the implementation. With libgomp it >>>>> return 0. With the check it should also return 0. >>>>> >>>>>> It would be in the interest of less semantic differences w.r.t. range >>>>>> to >>>>>> deal better with this case. >>>>>> >>>>>> Will it silence the warning if we make "i" firstprivate as well as >>>>>> lastprivate? firstprivate would only affect the case of zero >>>>>> iterations, >>>>>> since we overwrite with NaN if the loop is entered... >>>>> >>>>> Well, it wouldn't be NaN, it would be start + step * temp :) But, yes, >>>> >>>> Doh. >>>> >>>>> that works. So we need both the check and an initialization in there: >>>>> >>>>> if (nsteps> ? ?0) { >>>>> ? ? i = 0; >>>>> ? ? #pragma omp parallel for firstprivate(i) lastprivate(i) >>>>> ? ? for (temp = 0; ...; ...) ... >>>>> } >>>> >>>> Why do you need the if-test? Won't simply >>>> >>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>> for (temp = 0; ...; ...) ... >>>> >>>> do the job -- any initial value will be copied into all threads, >>>> including >>>> the "last" thread, even if there are no iterations? >>> >>> It will, but you don't expect your iteration variable to change with >>> zero iterations. >> >> Look. >> >> i = 42 >> for i in prange(n): >> ? ?f(i) >> print i # want 42 whenever n == 0 >> >> Now, translate this to: >> >> i = 42; >> #pragma omp parallel for firstprivate(i) lastprivate(i) >> for (temp = 0; ...; ...) { >> ? ?i = ... >> } >> #pragma omp parallel end >> /* At this point, i == 42 if n == 0 */ >> >> Am I missing something? > > Yes, 'i' may be uninitialized with nsteps > 0 (this should be valid > code). So if nsteps > 0, we need to initialize 'i' to something to get > correct behaviour with firstprivate. > And of course, if you initialize 'i' unconditionally, you change 'i' whereas you might have to leave it unaffected. From d.s.seljebotn at astro.uio.no Wed May 4 13:54:18 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 13:54:18 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> Message-ID: <4DC13E6A.2080408@astro.uio.no> On 05/04/2011 01:48 PM, mark florisson wrote: > On 4 May 2011 13:47, mark florisson wrote: >> On 4 May 2011 13:45, Dag Sverre Seljebotn wrote: >>> Look. >>> >>> i = 42 >>> for i in prange(n): >>> f(i) >>> print i # want 42 whenever n == 0 >>> >>> Now, translate this to: >>> >>> i = 42; >>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>> for (temp = 0; ...; ...) { >>> i = ... >>> } >>> #pragma omp parallel end >>> /* At this point, i == 42 if n == 0 */ >>> >>> Am I missing something? >> >> Yes, 'i' may be uninitialized with nsteps> 0 (this should be valid >> code). So if nsteps> 0, we need to initialize 'i' to something to get >> correct behaviour with firstprivate. This I don't see. I think I need to be spoon-fed on this one. > And of course, if you initialize 'i' unconditionally, you change 'i' > whereas you might have to leave it unaffected. This I see. Dag Sverre From markflorisson88 at gmail.com Wed May 4 13:59:29 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 13:59:29 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC13E6A.2080408@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA743EF.7080200@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> Message-ID: On 4 May 2011 13:54, Dag Sverre Seljebotn wrote: > On 05/04/2011 01:48 PM, mark florisson wrote: >> >> On 4 May 2011 13:47, mark florisson ?wrote: >>> >>> On 4 May 2011 13:45, Dag Sverre Seljebotn >>> ?wrote: > >>>> Look. >>>> >>>> i = 42 >>>> for i in prange(n): >>>> ? ?f(i) >>>> print i # want 42 whenever n == 0 >>>> >>>> Now, translate this to: >>>> >>>> i = 42; >>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>> for (temp = 0; ...; ...) { >>>> ? ?i = ... >>>> } >>>> #pragma omp parallel end >>>> /* At this point, i == 42 if n == 0 */ >>>> >>>> Am I missing something? >>> >>> Yes, 'i' may be uninitialized with nsteps> ?0 (this should be valid >>> code). So if nsteps> ?0, we need to initialize 'i' to something to get >>> correct behaviour with firstprivate. > > This I don't see. I think I need to be spoon-fed on this one. So assume this code cdef int i for i in prange(10): ... Now if we transform this without the guard we get int i; #pragma omp parallel for firstprivate(i) lastprivate(i) for (...) { ...} This is invalid C code, but valid Cython code. So we need to initialize 'i', but then we get our "leave it unaffected for 0 iterations" paradox. So we need a guard. >> ?And of course, if you initialize 'i' unconditionally, you change 'i' >> whereas you might have to leave it unaffected. > > This I see. > > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Wed May 4 14:10:06 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 14:10:06 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> Message-ID: <4DC1421E.60407@astro.uio.no> On 05/04/2011 01:59 PM, mark florisson wrote: > On 4 May 2011 13:54, Dag Sverre Seljebotn wrote: >> On 05/04/2011 01:48 PM, mark florisson wrote: >>> >>> On 4 May 2011 13:47, mark florisson wrote: >>>> >>>> On 4 May 2011 13:45, Dag Sverre Seljebotn >>>> wrote: >> >>>>> Look. >>>>> >>>>> i = 42 >>>>> for i in prange(n): >>>>> f(i) >>>>> print i # want 42 whenever n == 0 >>>>> >>>>> Now, translate this to: >>>>> >>>>> i = 42; >>>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>>> for (temp = 0; ...; ...) { >>>>> i = ... >>>>> } >>>>> #pragma omp parallel end >>>>> /* At this point, i == 42 if n == 0 */ >>>>> >>>>> Am I missing something? >>>> >>>> Yes, 'i' may be uninitialized with nsteps> 0 (this should be valid >>>> code). So if nsteps> 0, we need to initialize 'i' to something to get >>>> correct behaviour with firstprivate. >> >> This I don't see. I think I need to be spoon-fed on this one. > > So assume this code > > cdef int i > > for i in prange(10): ... > > Now if we transform this without the guard we get > > int i; > > #pragma omp parallel for firstprivate(i) lastprivate(i) > for (...) { ...} > > This is invalid C code, but valid Cython code. So we need to > initialize 'i', but then we get our "leave it unaffected for 0 > iterations" paradox. So we need a guard. You mean C code won't compile if i is firstprivate and not initialized? (Sorry, I'm not aware of such things.) My first instinct is to initialize i to 0xbadabada. After all, its value is not specified -- we're not violating any Cython specs by initializing it to garbage ourselves. OTOH, I see that your approach with an if-test is more Valgrind-friendly, so I'm OK with that. Would it work to do if (nsteps > 0) { #pragma omp parallel i = 0; #pragma omp for lastprivate(i) for (temp = 0; ...) ... ... } instead, to get rid of the warning without using a firstprivate? Not sure if there's an efficiency difference here, I suppose a good C compiler could compile them to the same thing. Dag Sverre From markflorisson88 at gmail.com Wed May 4 14:17:43 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 14:17:43 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC1421E.60407@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> Message-ID: On 4 May 2011 14:10, Dag Sverre Seljebotn wrote: > On 05/04/2011 01:59 PM, mark florisson wrote: >> >> On 4 May 2011 13:54, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/04/2011 01:48 PM, mark florisson wrote: >>>> >>>> On 4 May 2011 13:47, mark florisson ? ?wrote: >>>>> >>>>> On 4 May 2011 13:45, Dag Sverre Seljebotn >>>>> ?wrote: >>> >>>>>> Look. >>>>>> >>>>>> i = 42 >>>>>> for i in prange(n): >>>>>> ? ?f(i) >>>>>> print i # want 42 whenever n == 0 >>>>>> >>>>>> Now, translate this to: >>>>>> >>>>>> i = 42; >>>>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>>>> for (temp = 0; ...; ...) { >>>>>> ? ?i = ... >>>>>> } >>>>>> #pragma omp parallel end >>>>>> /* At this point, i == 42 if n == 0 */ >>>>>> >>>>>> Am I missing something? >>>>> >>>>> Yes, 'i' may be uninitialized with nsteps> ? ?0 (this should be valid >>>>> code). So if nsteps> ? ?0, we need to initialize 'i' to something to >>>>> get >>>>> correct behaviour with firstprivate. >>> >>> This I don't see. I think I need to be spoon-fed on this one. >> >> So assume this code >> >> cdef int i >> >> for i in prange(10): ... >> >> Now if we transform this without the guard we get >> >> int i; >> >> #pragma omp parallel for firstprivate(i) lastprivate(i) >> for (...) { ...} >> >> This is invalid C code, but valid Cython code. So we need to >> initialize 'i', but then we get our "leave it unaffected for 0 >> iterations" paradox. So we need a guard. > > You mean C code won't compile if i is firstprivate and not initialized? > (Sorry, I'm not aware of such things.) It will compile and warn, but it is technically invalid, as you're reading an uninitialized variable, which has undefined behavior. If e.g. the variable contains a trap representation on a certain architecture, it might halt the program (I'm not sure which architecture that would be, but I believe they exist). > My first instinct is to initialize i to 0xbadabada. After all, its value is > not specified -- we're not violating any Cython specs by initializing it to > garbage ourselves. The problem is that we don't know whether the user has initialized the variable. So if we want firstprivate to suppress warnings, we should assume that the user hasn't and do it ourselves. > OTOH, I see that your approach with an if-test is more Valgrind-friendly, so > I'm OK with that. > > Would it work to do > > if (nsteps > 0) { > ? ?#pragma omp parallel > ? ?i = 0; > ? ?#pragma omp for lastprivate(i) > ? ?for (temp = 0; ...) ... > ? ?... > } I'm assuming you mean #pragma omp parallel private(i), otherwise you have a race (I'm not sure how much that matters for assignment). In any case, with the private() clause 'i' would be uninitialized afterwards. In either case it won't do anything useful. > instead, to get rid of the warning without using a firstprivate? Not sure if > there's an efficiency difference here, I suppose a good C compiler could > compile them to the same thing. > > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From markflorisson88 at gmail.com Wed May 4 14:19:47 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 14:19:47 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA74CEC.2000609@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> Message-ID: On 4 May 2011 14:17, mark florisson wrote: > On 4 May 2011 14:10, Dag Sverre Seljebotn wrote: >> On 05/04/2011 01:59 PM, mark florisson wrote: >>> >>> On 4 May 2011 13:54, Dag Sverre Seljebotn >>> ?wrote: >>>> >>>> On 05/04/2011 01:48 PM, mark florisson wrote: >>>>> >>>>> On 4 May 2011 13:47, mark florisson ? ?wrote: >>>>>> >>>>>> On 4 May 2011 13:45, Dag Sverre Seljebotn >>>>>> ?wrote: >>>> >>>>>>> Look. >>>>>>> >>>>>>> i = 42 >>>>>>> for i in prange(n): >>>>>>> ? ?f(i) >>>>>>> print i # want 42 whenever n == 0 >>>>>>> >>>>>>> Now, translate this to: >>>>>>> >>>>>>> i = 42; >>>>>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>>>>> for (temp = 0; ...; ...) { >>>>>>> ? ?i = ... >>>>>>> } >>>>>>> #pragma omp parallel end >>>>>>> /* At this point, i == 42 if n == 0 */ >>>>>>> >>>>>>> Am I missing something? >>>>>> >>>>>> Yes, 'i' may be uninitialized with nsteps> ? ?0 (this should be valid >>>>>> code). So if nsteps> ? ?0, we need to initialize 'i' to something to >>>>>> get >>>>>> correct behaviour with firstprivate. >>>> >>>> This I don't see. I think I need to be spoon-fed on this one. >>> >>> So assume this code >>> >>> cdef int i >>> >>> for i in prange(10): ... >>> >>> Now if we transform this without the guard we get >>> >>> int i; >>> >>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>> for (...) { ...} >>> >>> This is invalid C code, but valid Cython code. So we need to >>> initialize 'i', but then we get our "leave it unaffected for 0 >>> iterations" paradox. So we need a guard. >> >> You mean C code won't compile if i is firstprivate and not initialized? >> (Sorry, I'm not aware of such things.) > > It will compile and warn, but it is technically invalid, as you're > reading an uninitialized variable, which has undefined behavior. If > e.g. the variable contains a trap representation on a certain > architecture, it might halt the program (I'm not sure which > architecture that would be, but I believe they exist). > >> My first instinct is to initialize i to 0xbadabada. After all, its value is >> not specified -- we're not violating any Cython specs by initializing it to >> garbage ourselves. > > The problem is that we don't know whether the user has initialized the > variable. So if we want firstprivate to suppress warnings, we should > assume that the user hasn't and do it ourselves. The alternative would be to give 'cdef int i' initialized semantics, to whatever value we please. So instead of generating 'int i;' code, we could always generate 'int i = ...;'. But currently we don't do that. >> OTOH, I see that your approach with an if-test is more Valgrind-friendly, so >> I'm OK with that. >> >> Would it work to do >> >> if (nsteps > 0) { >> ? ?#pragma omp parallel >> ? ?i = 0; >> ? ?#pragma omp for lastprivate(i) >> ? ?for (temp = 0; ...) ... >> ? ?... >> } > > I'm assuming you mean #pragma omp parallel private(i), otherwise you > have a race (I'm not sure how much that matters for assignment). In > any case, with the private() clause 'i' would be uninitialized > afterwards. In either case it won't do anything useful. > >> instead, to get rid of the warning without using a firstprivate? Not sure if >> there's an efficiency difference here, I suppose a good C compiler could >> compile them to the same thing. >> >> Dag Sverre >> _______________________________________________ >> cython-devel mailing list >> cython-devel at python.org >> http://mail.python.org/mailman/listinfo/cython-devel >> > From d.s.seljebotn at astro.uio.no Wed May 4 14:23:07 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 14:23:07 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> Message-ID: <4DC1452B.7030801@astro.uio.no> On 05/04/2011 02:17 PM, mark florisson wrote: > On 4 May 2011 14:10, Dag Sverre Seljebotn wrote: >> On 05/04/2011 01:59 PM, mark florisson wrote: >>> >>> On 4 May 2011 13:54, Dag Sverre Seljebotn >>> wrote: >>>> >>>> On 05/04/2011 01:48 PM, mark florisson wrote: >>>>> >>>>> On 4 May 2011 13:47, mark florisson wrote: >>>>>> >>>>>> On 4 May 2011 13:45, Dag Sverre Seljebotn >>>>>> wrote: >>>> >>>>>>> Look. >>>>>>> >>>>>>> i = 42 >>>>>>> for i in prange(n): >>>>>>> f(i) >>>>>>> print i # want 42 whenever n == 0 >>>>>>> >>>>>>> Now, translate this to: >>>>>>> >>>>>>> i = 42; >>>>>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>>>>> for (temp = 0; ...; ...) { >>>>>>> i = ... >>>>>>> } >>>>>>> #pragma omp parallel end >>>>>>> /* At this point, i == 42 if n == 0 */ >>>>>>> >>>>>>> Am I missing something? >>>>>> >>>>>> Yes, 'i' may be uninitialized with nsteps> 0 (this should be valid >>>>>> code). So if nsteps> 0, we need to initialize 'i' to something to >>>>>> get >>>>>> correct behaviour with firstprivate. >>>> >>>> This I don't see. I think I need to be spoon-fed on this one. >>> >>> So assume this code >>> >>> cdef int i >>> >>> for i in prange(10): ... >>> >>> Now if we transform this without the guard we get >>> >>> int i; >>> >>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>> for (...) { ...} >>> >>> This is invalid C code, but valid Cython code. So we need to >>> initialize 'i', but then we get our "leave it unaffected for 0 >>> iterations" paradox. So we need a guard. >> >> You mean C code won't compile if i is firstprivate and not initialized? >> (Sorry, I'm not aware of such things.) > > It will compile and warn, but it is technically invalid, as you're > reading an uninitialized variable, which has undefined behavior. If > e.g. the variable contains a trap representation on a certain > architecture, it might halt the program (I'm not sure which > architecture that would be, but I believe they exist). > >> My first instinct is to initialize i to 0xbadabada. After all, its value is >> not specified -- we're not violating any Cython specs by initializing it to >> garbage ourselves. > > The problem is that we don't know whether the user has initialized the > variable. So if we want firstprivate to suppress warnings, we should > assume that the user hasn't and do it ourselves. I meant that if we don't care about Valgrindability, we can initialize i at the top of our function (i.e. where it says "int __pyx_v_i"). >> OTOH, I see that your approach with an if-test is more Valgrind-friendly, so >> I'm OK with that. >> >> Would it work to do >> >> if (nsteps> 0) { >> #pragma omp parallel >> i = 0; >> #pragma omp for lastprivate(i) >> for (temp = 0; ...) ... >> ... >> } > > I'm assuming you mean #pragma omp parallel private(i), otherwise you > have a race (I'm not sure how much that matters for assignment). In > any case, with the private() clause 'i' would be uninitialized > afterwards. In either case it won't do anything useful. Sorry, I meant that lastprivate(i) should go on the parallel line. if (nsteps> 0) { #pragma omp parallel lastprivate(i) i = 0; #pragma omp for for (temp = 0; ...) ... ... } won't this silence the warning? At any rate, it's obvious you have a better handle on this than me, so I'll shut up now and leave you to it :-) Dag Sverre From markflorisson88 at gmail.com Wed May 4 14:38:41 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 14:38:41 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC1452B.7030801@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DA9C6DF.1060406@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> Message-ID: On 4 May 2011 14:23, Dag Sverre Seljebotn wrote: > On 05/04/2011 02:17 PM, mark florisson wrote: >> >> On 4 May 2011 14:10, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/04/2011 01:59 PM, mark florisson wrote: >>>> >>>> On 4 May 2011 13:54, Dag Sverre Seljebotn >>>> ?wrote: >>>>> >>>>> On 05/04/2011 01:48 PM, mark florisson wrote: >>>>>> >>>>>> On 4 May 2011 13:47, mark florisson >>>>>> ?wrote: >>>>>>> >>>>>>> On 4 May 2011 13:45, Dag Sverre Seljebotn >>>>>>> ?wrote: >>>>> >>>>>>>> Look. >>>>>>>> >>>>>>>> i = 42 >>>>>>>> for i in prange(n): >>>>>>>> ? ?f(i) >>>>>>>> print i # want 42 whenever n == 0 >>>>>>>> >>>>>>>> Now, translate this to: >>>>>>>> >>>>>>>> i = 42; >>>>>>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>>>>>> for (temp = 0; ...; ...) { >>>>>>>> ? ?i = ... >>>>>>>> } >>>>>>>> #pragma omp parallel end >>>>>>>> /* At this point, i == 42 if n == 0 */ >>>>>>>> >>>>>>>> Am I missing something? >>>>>>> >>>>>>> Yes, 'i' may be uninitialized with nsteps> ? ? ?0 (this should be >>>>>>> valid >>>>>>> code). So if nsteps> ? ? ?0, we need to initialize 'i' to something >>>>>>> to >>>>>>> get >>>>>>> correct behaviour with firstprivate. >>>>> >>>>> This I don't see. I think I need to be spoon-fed on this one. >>>> >>>> So assume this code >>>> >>>> cdef int i >>>> >>>> for i in prange(10): ... >>>> >>>> Now if we transform this without the guard we get >>>> >>>> int i; >>>> >>>> #pragma omp parallel for firstprivate(i) lastprivate(i) >>>> for (...) { ...} >>>> >>>> This is invalid C code, but valid Cython code. So we need to >>>> initialize 'i', but then we get our "leave it unaffected for 0 >>>> iterations" paradox. So we need a guard. >>> >>> You mean C code won't compile if i is firstprivate and not initialized? >>> (Sorry, I'm not aware of such things.) >> >> It will compile and warn, but it is technically invalid, as you're >> reading an uninitialized variable, which has undefined behavior. If >> e.g. the variable contains a trap representation on a certain >> architecture, it might halt the program (I'm not sure which >> architecture that would be, but I believe they exist). >> >>> My first instinct is to initialize i to 0xbadabada. After all, its value >>> is >>> not specified -- we're not violating any Cython specs by initializing it >>> to >>> garbage ourselves. >> >> The problem is that we don't know whether the user has initialized the >> variable. So if we want firstprivate to suppress warnings, we should >> assume that the user hasn't and do it ourselves. > > I meant that if we don't care about Valgrindability, we can initialize i at > the top of our function (i.e. where it says "int __pyx_v_i"). Indeed, but as the current semantics don't do this, I think we also shouldn't. The good thing is that if we don't do it, the user will see warnings from the C compiler if used uninitialized. >>> OTOH, I see that your approach with an if-test is more Valgrind-friendly, >>> so >>> I'm OK with that. >>> >>> Would it work to do >>> >>> if (nsteps> ?0) { >>> ? ?#pragma omp parallel >>> ? ?i = 0; >>> ? ?#pragma omp for lastprivate(i) >>> ? ?for (temp = 0; ...) ... >>> ? ?... >>> } >> >> I'm assuming you mean #pragma omp parallel private(i), otherwise you >> have a race (I'm not sure how much that matters for assignment). In >> any case, with the private() clause 'i' would be uninitialized >> afterwards. In either case it won't do anything useful. > > Sorry, I meant that lastprivate(i) should go on the parallel line. > > if (nsteps> ?0) { > ? ?#pragma omp parallel lastprivate(i) > ? ?i = 0; > ? ?#pragma omp for > ? ?for (temp = 0; ...) ... > ? ?... > } > > won't this silence the warning? At any rate, it's obvious you have a better > handle on this than me, so I'll shut up now and leave you to it :-) lastprivate() is not valid on a plain parallel constructs, as it's not a loop. There's only private() and shared(). From d.s.seljebotn at astro.uio.no Wed May 4 18:35:36 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 18:35:36 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> Message-ID: <4DC18058.5040101@astro.uio.no> Moving pull requestion discussion (https://github.com/cython/cython/pull/28) over here: First, I got curious why you'd have a strip off "-pthread" from CC. I'd think you could just execute with it with "-pthread", which seems simpler. Second: If parallel.parallel is not callable, how are scheduling parameters for parallel blocks handled? Is there a reason to not support that? Do you think it should stay this way, or will parallel take parameters in the future? Dag Sverre From markflorisson88 at gmail.com Wed May 4 19:03:27 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 19:03:27 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC18058.5040101@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <62739f06-a6e9-4cd9-99bd-e3af674fdc61@email.android.com> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> <4DC18058.5040101@astro.uio.no> Message-ID: On 4 May 2011 18:35, Dag Sverre Seljebotn wrote: > Moving pull requestion discussion (https://github.com/cython/cython/pull/28) > over here: > > First, I got curious why you'd have a strip off "-pthread" from CC. I'd > think you could just execute with it with "-pthread", which seems simpler. It needs to end up in a list of arguments, and it's not needed at all as I only need the version. I guess I could do (cc + " -v").split() but eh. > Second: If parallel.parallel is not callable, how are scheduling parameters > for parallel blocks handled? Is there a reason to not support that? Do you > think it should stay this way, or will parallel take parameters in the > future? Well, as I mentioned a while back, you cannot schedule parallel blocks, there is no worksharing involved. All a parallel block does is executed a code block in however many threads there are available. The scheduling parameters are valid for a worksharing for loop only, as you schedule (read "distribute") the work among the threads. > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Wed May 4 19:44:50 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 19:44:50 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> <4DC18058.5040101@astro.uio.no> Message-ID: <4DC19092.1030503@astro.uio.no> On 05/04/2011 07:03 PM, mark florisson wrote: > On 4 May 2011 18:35, Dag Sverre Seljebotn wrote: >> Moving pull requestion discussion (https://github.com/cython/cython/pull/28) >> over here: >> >> First, I got curious why you'd have a strip off "-pthread" from CC. I'd >> think you could just execute with it with "-pthread", which seems simpler. > > It needs to end up in a list of arguments, and it's not needed at all > as I only need the version. I guess I could do (cc + " -v").split() > but eh. OK, that's reassuring, thought perhaps you had encountered a strange gcc strain. > >> Second: If parallel.parallel is not callable, how are scheduling parameters >> for parallel blocks handled? Is there a reason to not support that? Do you >> think it should stay this way, or will parallel take parameters in the >> future? > > Well, as I mentioned a while back, you cannot schedule parallel > blocks, there is no worksharing involved. All a parallel block does is > executed a code block in however many threads there are available. The > scheduling parameters are valid for a worksharing for loop only, as > you schedule (read "distribute") the work among the threads. Perhaps I used the wrong terms; but checking the specs, I guess I meant "num_threads", which definitely applies to parallel. Dag Sverre From markflorisson88 at gmail.com Wed May 4 20:07:55 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 20:07:55 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC19092.1030503@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> <4DC18058.5040101@astro.uio.no> <4DC19092.1030503@astro.uio.no> Message-ID: On 4 May 2011 19:44, Dag Sverre Seljebotn wrote: > On 05/04/2011 07:03 PM, mark florisson wrote: >> >> On 4 May 2011 18:35, Dag Sverre Seljebotn >> ?wrote: >>> >>> Moving pull requestion discussion >>> (https://github.com/cython/cython/pull/28) >>> over here: >>> >>> First, I got curious why you'd have a strip off "-pthread" from CC. I'd >>> think you could just execute with it with "-pthread", which seems >>> simpler. >> >> It needs to end up in a list of arguments, and it's not needed at all >> as I only need the version. I guess I could do (cc + " -v").split() >> but eh. > > OK, that's reassuring, thought perhaps you had encountered a strange gcc > strain. > >> >>> Second: If parallel.parallel is not callable, how are scheduling >>> parameters >>> for parallel blocks handled? Is there a reason to not support that? Do >>> you >>> think it should stay this way, or will parallel take parameters in the >>> future? >> >> Well, as I mentioned a while back, you cannot schedule parallel >> blocks, there is no worksharing involved. All a parallel block does is >> executed a code block in however many threads there are available. The >> scheduling parameters are valid for a worksharing for loop only, as >> you schedule (read "distribute") the work among the threads. > > Perhaps I used the wrong terms; but checking the specs, I guess I meant > "num_threads", which definitely applies to parallel. Ah, that level of scheduling :) Right, so it doesn't take that, but I don't think it's a big issue. If dynamic scheduling is enabled, it's only a suggestion, if dynamic scheduling is disabled (whether it's turned on or off by default is implementation defined) it will give the the amount of threads requested, if available. The user can still use omp_set_num_threads(), although admittedly that modifies a global setting. > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From robertwb at math.washington.edu Wed May 4 20:13:48 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Wed, 4 May 2011 11:13:48 -0700 Subject: [Cython] Fused Types In-Reply-To: References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC08A97.5070009@canterbury.ac.nz> <4DC10D4F.8010209@astro.uio.no> Message-ID: On Wed, May 4, 2011 at 1:47 AM, mark florisson wrote: > On 4 May 2011 10:24, Dag Sverre Seljebotn wrote: >> On 05/04/2011 01:07 AM, Greg Ewing wrote: >>> >>> mark florisson wrote: >>> >>>> cdef func(floating x, floating y): >>>> ... >>>> >>>> you get a "float, float" version, and a "double, double" version, but >>>> not "float, double" or "double, float". >>> >>> It's hard to draw conclusions from this example because >>> it's degenerate. You don't really need multiple versions of a >>> function like that, because of float <-> double coercions. >>> >>> A more telling example might be >>> >>> cdef double dot_product(floating *u, floating *v, int length) >>> >>> By your current rules, this would give you one version that >>> takes two float vectors, and another that takes two double >>> vectors. >>> >>> But if you want to find the dot product of a float vector and >>> a double vector, you're out of luck. >> >> First, I'm open for your proposed syntax too...But in the interest of seeing >> how we got here: >> >> The argument to the above goes that you *should* be out of luck. For >> instance, talking about dot products, BLAS itself has float-float and >> double-double, but not float-double AFAIK. >> >> What you are saying that this does not have the full power of C++ templates. >> And the answer is that yes, this does not have the full power of C++ >> templates. >> >> At the same time we discussed this, we also discussed better support for >> string-based templating languages (so that, e.g., compilation error messages >> could refer to the template file). The two are complementary. >> >> Going back to Greg's syntax: What I don't like is that it makes the simple >> unambiguous cases, where this would actually be used in real life, less >> readable. >> >> Would it be too complicated to have both? For instance; >> >> ?i) You are allowed to use a *single* fused_type on a *function* without >> declaration. >> >> def f(floating x, floating *y): # ok >> >> Turns into >> >> def f[floating T](T x, T *y): >> >> This is NOT ok: >> >> def f(floating x, integral y): >> # ERROR: Please explicitly declare fused types inside [] >> >> ?ii) Using more than one fused type, or using it on a cdef class or struct, >> you need to use the [] declaration. >> > > I don't think it would be too complicated, but as you mention it's > probably not a very likely case, and if the user does need it, a new > (equivalent) fused type can be created. The current way reads a lot > nicer than the indexed one in my opinion. So I'd be fine with > implementing it, but I find the current way more elegant. I was actually thinking of exactly the same thing--supporting syntax (i) for the case of a single type parameter, but the drawback is the introduction of two distinct syntaxes for essentially the same feature. Something like this is necessary to give an ordering to the types for structs and classes, or when a fused type is used for intermediate results but not in the argument list. I really like the elegance of the (much more common) single-parameter variant. Another option is using the with syntax, which was also considered for supporting C++ templates. >> Finally: It is a bit uncomfortable that we seem to be hashing things out >> even as Mark is implementing this. Would it be feasible to have a Skype >> session sometimes this week where everybody interested in the outcome of >> this come together for an hour and actually decide on something? >> >> Mark: How much does this discussion of syntax impact your development? Are >> you able to treat them just as polish on top and work on the "engine" >> undisturbed by this? > > Thanks for your consideration, I admit it it feels a bit uncomfortable > :) But at least this change shouldn't have such a big impact on the > code, it would mean some changes in a select few places, so it's > definitely polish. In any event, before we settle on this, I'd like to > do the cpdef support first and work on indexing from Python space, so > I think we have enough time to settle this argument on the ML. > Before that, I'm just going to finish up for a pull request for the > OpenMP branch, I'd like to see if I can get rid of some warnings. Yes, please feel free to focus on the back end and move onto other the things while the syntax is still in limbo, rather than implementing every whim of the mailing list :). - Robert From yury at shurup.com Wed May 4 20:36:34 2011 From: yury at shurup.com (Yury V. Zaytsev) Date: Wed, 04 May 2011 20:36:34 +0200 Subject: [Cython] jenkins problems In-Reply-To: References: Message-ID: <1304534194.2492.6.camel@newpride> On Wed, 2011-05-04 at 10:35 +0400, Vitja Makarov wrote: > > Can you please provide me jenkins account and I'll try to fix the issues myself? > > > > It's better to use: > > $ git fetch origin > $ git checkout -f origin/master > > Instead of git pull Or $ git fetch origin $ git reset --hard origin/master which is what we used for our buildbot. -- Sincerely yours, Yury V. Zaytsev From vitja.makarov at gmail.com Wed May 4 20:43:14 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 4 May 2011 22:43:14 +0400 Subject: [Cython] jenkins problems In-Reply-To: <1304534194.2492.6.camel@newpride> References: <1304534194.2492.6.camel@newpride> Message-ID: 2011/5/4 Yury V. Zaytsev : > On Wed, 2011-05-04 at 10:35 +0400, Vitja Makarov wrote: >> > Can you please provide me jenkins account and I'll try to fix the issues myself? >> > >> >> It's better to use: >> >> $ git fetch origin >> $ git checkout -f origin/master >> >> Instead of git pull > > Or > > $ git fetch origin > $ git reset --hard origin/master > > which is what we used for our buildbot. > > -- > Sincerely yours, > Yury V. Zaytsev > Thanks! Am I right: when you do reset '--hard origin/master' you are on the master branch and when you do checkout you are in a 'detached state'? But it seems to me that the problem is somewhere in the jenkins configuration. -- vitja. From yury at shurup.com Wed May 4 20:57:19 2011 From: yury at shurup.com (Yury V. Zaytsev) Date: Wed, 04 May 2011 20:57:19 +0200 Subject: [Cython] jenkins problems In-Reply-To: References: <1304534194.2492.6.camel@newpride> Message-ID: <1304535439.2492.17.camel@newpride> On Wed, 2011-05-04 at 22:43 +0400, Vitja Makarov wrote: > Thanks! Am I right: when you do reset '--hard origin/master' you are > on the master branch and when you do checkout you are in a 'detached > state'? Yes, I think that you are right, that's why we used to do reset instead: $ git fetch origin $ git checkout master $ git reset --hard origin/master By the way, you can also do $ git clean -dfx to make sure that EVERYTHING that doesn't belong to the tree is plainly wiped out (don't do that on your real checkouts unless you definitively have nothing to lose). > But it seems to me that the problem is somewhere in the jenkins configuration. I didn't mean to say that there's no problem with Jenkins, just wanted to suggest a possibly better way of updating the CI checkout :-) -- Sincerely yours, Yury V. Zaytsev From stefan_ml at behnel.de Wed May 4 21:07:11 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Wed, 04 May 2011 21:07:11 +0200 Subject: [Cython] jenkins problems In-Reply-To: References: Message-ID: <4DC1A3DF.2070007@behnel.de> Vitja Makarov, 04.05.2011 07:09: > Jenkins doesn't work for me. It seems that it can't do pull and is > running tests again obsolete sources. > May be because of forced push. > > There are only 6 errors here: > https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ According to the build logs of the sdist job, it was previously checking out the "master" branch and it seems you reconfigured it to use the "unreachable_code" branch now. At least the recent checkouts have used the latest snapshot of the branches, so ISTM that everything is working correctly. Could you point me to a build where something was going wrong for you? Stefan From d.s.seljebotn at astro.uio.no Wed May 4 21:13:09 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 21:13:09 +0200 Subject: [Cython] prange CEP updated In-Reply-To: References: <4D9B7BA9.2060509@astro.uio.no> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> <4DC18058.5040101@astro.uio.no> <4DC19092.1030503@astro.uio.no> Message-ID: <4DC1A545.70304@astro.uio.no> On 05/04/2011 08:07 PM, mark florisson wrote: > On 4 May 2011 19:44, Dag Sverre Seljebotn wrote: >> On 05/04/2011 07:03 PM, mark florisson wrote: >>> >>> On 4 May 2011 18:35, Dag Sverre Seljebotn >>> wrote: >>>> >>>> Moving pull requestion discussion >>>> (https://github.com/cython/cython/pull/28) >>>> over here: >>>> >>>> First, I got curious why you'd have a strip off "-pthread" from CC. I'd >>>> think you could just execute with it with "-pthread", which seems >>>> simpler. >>> >>> It needs to end up in a list of arguments, and it's not needed at all >>> as I only need the version. I guess I could do (cc + " -v").split() >>> but eh. >> >> OK, that's reassuring, thought perhaps you had encountered a strange gcc >> strain. >> >>> >>>> Second: If parallel.parallel is not callable, how are scheduling >>>> parameters >>>> for parallel blocks handled? Is there a reason to not support that? Do >>>> you >>>> think it should stay this way, or will parallel take parameters in the >>>> future? >>> >>> Well, as I mentioned a while back, you cannot schedule parallel >>> blocks, there is no worksharing involved. All a parallel block does is >>> executed a code block in however many threads there are available. The >>> scheduling parameters are valid for a worksharing for loop only, as >>> you schedule (read "distribute") the work among the threads. >> >> Perhaps I used the wrong terms; but checking the specs, I guess I meant >> "num_threads", which definitely applies to parallel. > > Ah, that level of scheduling :) Right, so it doesn't take that, but I > don't think it's a big issue. If dynamic scheduling is enabled, it's > only a suggestion, if dynamic scheduling is disabled (whether it's > turned on or off by default is implementation defined) it will give > the the amount of threads requested, if available. > The user can still use omp_set_num_threads(), although admittedly that > modifies a global setting. Hmm...I'm not completely happy about this. For now I just worry about not shutting off the possibility of adding thread-pool-spawning parameters in the future. Specifying the number of threads can be useful, and omp_set_num_threads is a bad way of doing as you say. And other backends than OpenMP may call for something we don't know what is yet? Anyway, all I'm asking is whether we should require trailing () on parallel: with nogil, parallel(): ... I think we should, to keep the window open for options. Unless, that is, we're OK both with and without trailing () down the line. Dag Sverre From vitja.makarov at gmail.com Wed May 4 21:14:05 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 4 May 2011 23:14:05 +0400 Subject: [Cython] jenkins problems In-Reply-To: <4DC1A3DF.2070007@behnel.de> References: <4DC1A3DF.2070007@behnel.de> Message-ID: 2011/5/4 Stefan Behnel : > Vitja Makarov, 04.05.2011 07:09: >> >> Jenkins doesn't work for me. It seems that it can't do pull and is >> running tests again obsolete sources. >> May be because of forced push. >> >> There are only 6 errors here: >> >> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ > > According to the build logs of the sdist job, it was previously checking out > the "master" branch and it seems you reconfigured it to use the > "unreachable_code" branch now. At least the recent checkouts have used the > latest snapshot of the branches, so ISTM that everything is working > correctly. Could you point me to a build where something was going wrong for > you? > > Stefan I've added the following line to sdist target +rm -fr $WORKSPACE/dist $WORKSPACE/python/bin/python setup.py clean sdist --formats=gztar --cython-profile --no-cython-compile Hope that should help, that's the only difference between cython-devel-sdist and cython-vitek-sdist. See here: https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/166/ You can't find w_unreachable in the logs, it seems that cython code there is outdated. -- vitja. From d.s.seljebotn at astro.uio.no Wed May 4 21:17:34 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Wed, 04 May 2011 21:17:34 +0200 Subject: [Cython] Fused Types In-Reply-To: References: <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC08A97.5070009@canterbury.ac.nz> <4DC10D4F.8010209@astro.uio.no> Message-ID: <4DC1A64E.1090308@astro.uio.no> On 05/04/2011 08:13 PM, Robert Bradshaw wrote: > On Wed, May 4, 2011 at 1:47 AM, mark florisson > wrote: >> On 4 May 2011 10:24, Dag Sverre Seljebotn wrote: >>> On 05/04/2011 01:07 AM, Greg Ewing wrote: >>>> >>>> mark florisson wrote: >>>> >>>>> cdef func(floating x, floating y): >>>>> ... >>>>> >>>>> you get a "float, float" version, and a "double, double" version, but >>>>> not "float, double" or "double, float". >>>> >>>> It's hard to draw conclusions from this example because >>>> it's degenerate. You don't really need multiple versions of a >>>> function like that, because of float<-> double coercions. >>>> >>>> A more telling example might be >>>> >>>> cdef double dot_product(floating *u, floating *v, int length) >>>> >>>> By your current rules, this would give you one version that >>>> takes two float vectors, and another that takes two double >>>> vectors. >>>> >>>> But if you want to find the dot product of a float vector and >>>> a double vector, you're out of luck. >>> >>> First, I'm open for your proposed syntax too...But in the interest of seeing >>> how we got here: >>> >>> The argument to the above goes that you *should* be out of luck. For >>> instance, talking about dot products, BLAS itself has float-float and >>> double-double, but not float-double AFAIK. >>> >>> What you are saying that this does not have the full power of C++ templates. >>> And the answer is that yes, this does not have the full power of C++ >>> templates. >>> >>> At the same time we discussed this, we also discussed better support for >>> string-based templating languages (so that, e.g., compilation error messages >>> could refer to the template file). The two are complementary. >>> >>> Going back to Greg's syntax: What I don't like is that it makes the simple >>> unambiguous cases, where this would actually be used in real life, less >>> readable. >>> >>> Would it be too complicated to have both? For instance; >>> >>> i) You are allowed to use a *single* fused_type on a *function* without >>> declaration. >>> >>> def f(floating x, floating *y): # ok >>> >>> Turns into >>> >>> def f[floating T](T x, T *y): >>> >>> This is NOT ok: >>> >>> def f(floating x, integral y): >>> # ERROR: Please explicitly declare fused types inside [] >>> >>> ii) Using more than one fused type, or using it on a cdef class or struct, >>> you need to use the [] declaration. >>> >> >> I don't think it would be too complicated, but as you mention it's >> probably not a very likely case, and if the user does need it, a new >> (equivalent) fused type can be created. The current way reads a lot >> nicer than the indexed one in my opinion. So I'd be fine with >> implementing it, but I find the current way more elegant. > > I was actually thinking of exactly the same thing--supporting syntax > (i) for the case of a single type parameter, but the drawback is the > introduction of two distinct syntaxes for essentially the same > feature. Something like this is necessary to give an ordering to the > types for structs and classes, or when a fused type is used for > intermediate results but not in the argument list. I really like the > elegance of the (much more common) single-parameter variant. > > Another option is using the with syntax, which was also considered for > supporting C++ templates. In particular since that will work in pure Python mode. One thing I worry about with the func[]()-syntax is that it is not Python compatible. That's one thing I like about the CEP, that in time we can do def f(x: floating) -> floating: ... and have something that's nice in both Python and Cython. Dag Sverre From stefan_ml at behnel.de Wed May 4 21:24:27 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Wed, 04 May 2011 21:24:27 +0200 Subject: [Cython] jenkins problems In-Reply-To: References: <4DC1A3DF.2070007@behnel.de> Message-ID: <4DC1A7EB.6060107@behnel.de> Vitja Makarov, 04.05.2011 21:14: > 2011/5/4 Stefan Behnel: >> Vitja Makarov, 04.05.2011 07:09: >>> >>> Jenkins doesn't work for me. It seems that it can't do pull and is >>> running tests again obsolete sources. >>> May be because of forced push. >>> >>> There are only 6 errors here: >>> >>> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ >> >> According to the build logs of the sdist job, it was previously checking out >> the "master" branch and it seems you reconfigured it to use the >> "unreachable_code" branch now. At least the recent checkouts have used the >> latest snapshot of the branches, so ISTM that everything is working >> correctly. Could you point me to a build where something was going wrong for >> you? > > I've added the following line to sdist target > > +rm -fr $WORKSPACE/dist > $WORKSPACE/python/bin/python setup.py clean sdist --formats=gztar > --cython-profile --no-cython-compile > > Hope that should help, that's the only difference between > cython-devel-sdist and cython-vitek-sdist. > > > See here: > https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/166/ > > You can't find w_unreachable in the logs, it seems that cython code > there is outdated. Ah, right, that's it. You can see the problem here: https://sage.math.washington.edu:8091/hudson/job/cython-vitek-sdist/97/artifact/dist/Cython-0.14+.tar.gz/*fingerprint*/ It's been using the 0.14+ sdist for ages instead of the 0.14.1+ one. That could also explain why your CPython regression tests are running much faster than in cython-devel. Stefan From markflorisson88 at gmail.com Wed May 4 21:26:46 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Wed, 4 May 2011 21:26:46 +0200 Subject: [Cython] prange CEP updated In-Reply-To: <4DC1A545.70304@astro.uio.no> References: <4D9B7BA9.2060509@astro.uio.no> <4DB073BE.7010909@astro.uio.no> <4DC12E5D.8050508@astro.uio.no> <4DC1353D.2010607@astro.uio.no> <4DC13AE8.6010604@astro.uio.no> <4DC13C43.6050801@astro.uio.no> <4DC13E6A.2080408@astro.uio.no> <4DC1421E.60407@astro.uio.no> <4DC1452B.7030801@astro.uio.no> <4DC18058.5040101@astro.uio.no> <4DC19092.1030503@astro.uio.no> <4DC1A545.70304@astro.uio.no> Message-ID: On 4 May 2011 21:13, Dag Sverre Seljebotn wrote: > On 05/04/2011 08:07 PM, mark florisson wrote: >> >> On 4 May 2011 19:44, Dag Sverre Seljebotn >> ?wrote: >>> >>> On 05/04/2011 07:03 PM, mark florisson wrote: >>>> >>>> On 4 May 2011 18:35, Dag Sverre Seljebotn >>>> ?wrote: >>>>> >>>>> Moving pull requestion discussion >>>>> (https://github.com/cython/cython/pull/28) >>>>> over here: >>>>> >>>>> First, I got curious why you'd have a strip off "-pthread" from CC. I'd >>>>> think you could just execute with it with "-pthread", which seems >>>>> simpler. >>>> >>>> It needs to end up in a list of arguments, and it's not needed at all >>>> as I only need the version. I guess I could do (cc + " -v").split() >>>> but eh. >>> >>> OK, that's reassuring, thought perhaps you had encountered a strange gcc >>> strain. >>> >>>> >>>>> Second: If parallel.parallel is not callable, how are scheduling >>>>> parameters >>>>> for parallel blocks handled? Is there a reason to not support that? Do >>>>> you >>>>> think it should stay this way, or will parallel take parameters in the >>>>> future? >>>> >>>> Well, as I mentioned a while back, you cannot schedule parallel >>>> blocks, there is no worksharing involved. All a parallel block does is >>>> executed a code block in however many threads there are available. The >>>> scheduling parameters are valid for a worksharing for loop only, as >>>> you schedule (read "distribute") the work among the threads. >>> >>> Perhaps I used the wrong terms; but checking the specs, I guess I meant >>> "num_threads", which definitely applies to parallel. >> >> Ah, that level of scheduling :) Right, so it doesn't take that, but I >> don't think it's a big issue. If dynamic scheduling is enabled, it's >> only a suggestion, if dynamic scheduling is disabled (whether it's >> turned on or off by default is implementation defined) it will give >> the the amount of threads requested, if available. >> The user can still use omp_set_num_threads(), although admittedly that >> modifies a global setting. > > Hmm...I'm not completely happy about this. For now I just worry about not > shutting off the possibility of adding thread-pool-spawning parameters in > the future. Specifying the number of threads can be useful, and > omp_set_num_threads is a bad way of doing as you say. > > And other backends than OpenMP may call for something we don't know what is > yet? > > Anyway, all I'm asking is whether we should require trailing () on parallel: > > with nogil, parallel(): ... > > I think we should, to keep the window open for options. Unless, that is, > we're OK both with and without trailing () down the line. Ok, sure, that's fine with me. From vitja.makarov at gmail.com Wed May 4 21:29:50 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 4 May 2011 23:29:50 +0400 Subject: [Cython] jenkins problems In-Reply-To: <4DC1A7EB.6060107@behnel.de> References: <4DC1A3DF.2070007@behnel.de> <4DC1A7EB.6060107@behnel.de> Message-ID: 2011/5/4 Stefan Behnel : > Vitja Makarov, 04.05.2011 21:14: >> >> 2011/5/4 Stefan Behnel: >>> >>> Vitja Makarov, 04.05.2011 07:09: >>>> >>>> Jenkins doesn't work for me. It seems that it can't do pull and is >>>> running tests again obsolete sources. >>>> May be because of forced push. >>>> >>>> There are only 6 errors here: >>>> >>>> >>>> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/ >>> >>> According to the build logs of the sdist job, it was previously checking >>> out >>> the "master" branch and it seems you reconfigured it to use the >>> "unreachable_code" branch now. At least the recent checkouts have used >>> the >>> latest snapshot of the branches, so ISTM that everything is working >>> correctly. Could you point me to a build where something was going wrong >>> for >>> you? >> >> I've added the following line to sdist target >> >> +rm -fr $WORKSPACE/dist >> $WORKSPACE/python/bin/python setup.py clean sdist --formats=gztar >> --cython-profile --no-cython-compile >> >> Hope that should help, that's the only difference between >> cython-devel-sdist and cython-vitek-sdist. >> >> >> See here: >> >> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py27-c/166/ >> >> You can't find w_unreachable in the logs, it seems that cython code >> there is outdated. > > Ah, right, that's it. You can see the problem here: > > https://sage.math.washington.edu:8091/hudson/job/cython-vitek-sdist/97/artifact/dist/Cython-0.14+.tar.gz/*fingerprint*/ > > It's been using the 0.14+ sdist for ages instead of the 0.14.1+ one. > > That could also explain why your CPython regression tests are running much > faster than in cython-devel. > Ok, so I should take a look at pyregr tests closer. -- vitja. From greg.ewing at canterbury.ac.nz Wed May 4 23:53:30 2011 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 05 May 2011 09:53:30 +1200 Subject: [Cython] Fused Types In-Reply-To: <4DC10D4F.8010209@astro.uio.no> References: <4DB6D9FA.9030405@behnel.de> <4DBA1DF4.6010001@behnel.de> <4DBC1BA6.3030806@behnel.de> <4DBCA83D.6080405@canterbury.ac.nz> <4DBD601E.2060100@molden.no> <4DBD6FE0.8000200@behnel.de> <4DBD8991.2030307@molden.no> <4DBE7621.3080303@astro.uio.no> <4DBEAAD8.8000204@molden.no> <4DBEAE75.9020701@astro.uio.no> <4DBF970E.9050407@canterbury.ac.nz> <4DC08A97.5070009@canterbury.ac.nz> <4DC10D4F.8010209@astro.uio.no> Message-ID: <4DC1CADA.5060908@canterbury.ac.nz> Dag Sverre Seljebotn wrote: > The argument to the above goes that you *should* be out of luck. For > instance, talking about dot products, BLAS itself has float-float and > double-double, but not float-double AFAIK. Seems to me that's more because generating lots of versions of a function in C is hard work, and the designers of BLAS didn't think it was worth providing more than two versions. If they'd had a tool that would magically generate all the combinations for them, they might have made a different choice. What you seem to be trying to do here is enable compile-time duck typing, so that you can write a function that "just works" with a variety of argument types, without having to think about the details. With that mindset, seeing a function declared as cdef func(floating x, floating y) one would expect that x and y could be independently chosen as any of the types classified as "floating", because that's the way duck typing usually works. For example, if a Python function is documented as taking two sequences, you expect that to mean *any* two sequences, not two sequences of the same type. > > What you are saying that this does not have the full power of C++ > templates. And the answer is that yes, this does not have the full power > of C++ templates. What I'm suggesting doesn't have the full power of C++ templates either, because the range of possible values for each type parameter would still have to be specified in advance. However, it makes the dependencies between the type parameters explicit, rather than being hidden in some rather unintuitive implicit rules. > Would it be feasible to have a Skype > session sometimes this week where everybody interested in the outcome of > this come together for an hour and actually decide on something? I'm not sure that would help much. Reaching good decisions about things like this requires time to think through all the issues. -- Greg From vitja.makarov at gmail.com Thu May 5 08:41:35 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Thu, 5 May 2011 10:41:35 +0400 Subject: [Cython] Hudson pyregr testing takes too long In-Reply-To: References: <4D9DA400.4060105@behnel.de> <4D9DA560.8070505@behnel.de> <4DB50C05.5060701@behnel.de> <4DB53581.5090505@behnel.de> <4DB53DFE.9060601@behnel.de> Message-ID: 2011/4/25 Vitja Makarov : > 2011/4/25 Stefan Behnel : >> Vitja Makarov, 25.04.2011 11:04: >>> >>> 2011/4/25 Stefan Behnel: >>>> >>>> Vitja Makarov, 25.04.2011 08:19: >>>>> >>>>> 2011/4/25 Stefan Behnel: >>>>>> >>>>>> Stefan Behnel, 07.04.2011 13:52: >>>>>>> >>>>>>> Stefan Behnel, 07.04.2011 13:46: >>>>>>>> >>>>>>>> I just noticed that the CPython pyregr tests have jumped up from ~14 >>>>>>>> minutes for a run to ~4 hours when we added generator support. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> https://sage.math.washington.edu:8091/hudson/job/cython-devel-tests-pyregr-py26-c/buildTimeTrend >>>>>>>> >>>>>>>> I currently have no idea why that is (well, it's likely because we >>>>>>>> compile >>>>>>>> more tests now, but Vitja's branch ran the tests in ~30 minutes). It >>>>>>>> would >>>>>>>> be great if someone could find the time to analyse this problem. The >>>>>>>> current run time makes it basically impossible to keep these tests >>>>>>>> enabled. >>>>>>> >>>>>>> Ok, it looks like this is mostly an issue with the Py2.6 tests. The >>>>>>> Py2.7 >>>>>>> tests take 30-45 minutes, which is very long, but not completely out >>>>>>> of >>>>>>> bounds. I've disabled the Py2.6 pyregr tests for now. >>>>>> >>>>>> There seems to be a huge memory leak which almost certainly accounts >>>>>> for >>>>>> this. The Python process that runs the pyregr suite ends up with about >>>>>> 50GB >>>>>> of memory at the end, also in the latest Py3k builds. >>>>>> >>>>>> I have no idea where it may be, but it started to show when we merged >>>>>> the >>>>>> generator support. That's where I noticed the instant jump in the >>>>>> runtime. >>>>> >>>>> That's very strange for my branch it takes about 30 minutes that is ok. >>>> >>>> There's also a second path that's worth investigating. As part of the >>>> merge, >>>> there was another change that came in: the CythonPyregrTestCase >>>> implementation. This means that the regression tests are now being run >>>> differently than before. The massive memory consumption may simply be due >>>> to >>>> the mass of unit tests being loaded into memory. >>> >>> ? ?def run_test(): >>> .................................. >>> ? ? ? ? try: >>> ? ? ? ? ? ? module = __import__(self.module) >>> ? ? ? ? ? ? if hasattr(module, 'test_main'): >>> ? ? ? ? ? ? ? ? module.test_main() >>> ? ? ? ? except (unittest.SkipTest, support.ResourceDenied): >>> ? ? ? ? ? ? result.addSkip(self, 'ok') >>> >>> >>> It seems that all the modules stay loaded so may be they should be >>> unloaded with del sys.modules[module_name]? >> >> (Binary) module unloading isn't really supported in CPython. There's PEP >> 3121 that has the potential to change it, but it's not completely >> implemented, neither in CPython nor in Cython. A major problem is that >> unloading a module deletes its globals but not necessarily the code that >> uses them. For example, instances of types defined in the module can still >> be alive at that point. >> >> The way runtests.py deals with this is forking before loading a module. >> However, this does not currently work with the "xmlrunner" which we use on >> Hudson, so we let all tests run in a single process there. >> > > > Btw when running plain python code with generators total ref counter > doesn't get back to initial value. > I tried to trace scope and generator destructors and they are run as > expected. So I'm not sure about leaks in generators. > Recently I've found that pyregr.test_dict (test_mutatingiteration) test makes it slow: def test_mutatingiteration(): d = {} d[1] = 1 for i in d: print i d[i+1] = 1 test_mutatingiteration() In CPython this code raises: RuntimeError: dictionary changed size during iteration And in Cython you have infinite loop. So we can disable this test for now. -- vitja. From stefan_ml at behnel.de Thu May 5 09:18:22 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 05 May 2011 09:18:22 +0200 Subject: [Cython] Hudson pyregr testing takes too long In-Reply-To: References: <4D9DA400.4060105@behnel.de> <4D9DA560.8070505@behnel.de> <4DB50C05.5060701@behnel.de> <4DB53581.5090505@behnel.de> <4DB53DFE.9060601@behnel.de> Message-ID: <4DC24F3E.5090708@behnel.de> Vitja Makarov, 05.05.2011 08:41: > Recently I've found that pyregr.test_dict (test_mutatingiteration) > test makes it slow: > > def test_mutatingiteration(): > d = {} > d[1] = 1 > for i in d: > print i > d[i+1] = 1 > > test_mutatingiteration() > > > In CPython this code raises: RuntimeError: dictionary changed size > during iteration > And in Cython you have infinite loop. So we can disable this test for now. Interesting. Yes, if it's a bug in Cython then it's worth disabling the test until the bug is fixed. Anyway, I'll try to come up with a fix quickly. Stefan From vitja.makarov at gmail.com Thu May 5 16:29:02 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Thu, 5 May 2011 18:29:02 +0400 Subject: [Cython] Hudson pyregr testing takes too long In-Reply-To: <4DC24F3E.5090708@behnel.de> References: <4D9DA400.4060105@behnel.de> <4D9DA560.8070505@behnel.de> <4DB50C05.5060701@behnel.de> <4DB53581.5090505@behnel.de> <4DB53DFE.9060601@behnel.de> <4DC24F3E.5090708@behnel.de> Message-ID: 2011/5/5 Stefan Behnel : > Vitja Makarov, 05.05.2011 08:41: >> >> Recently I've found that pyregr.test_dict (test_mutatingiteration) >> test makes it slow: >> >> def test_mutatingiteration(): >> ? ? d = {} >> ? ? d[1] = 1 >> ? ? for i in d: >> ? ? ? ? print i >> ? ? ? ? d[i+1] = 1 >> >> test_mutatingiteration() >> >> >> In CPython this code raises: RuntimeError: dictionary changed size >> during iteration >> And in Cython you have infinite loop. So we can disable this test for now. > > Interesting. Yes, if it's a bug in Cython then it's worth disabling the test > until the bug is fixed. > > Anyway, I'll try to come up with a fix quickly. > Cool! It seems that you've fixed the issue and now pyregr takes about 40 minutes ) -- vitja. From stefan_ml at behnel.de Thu May 5 17:01:02 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 05 May 2011 17:01:02 +0200 Subject: [Cython] Hudson pyregr testing takes too long In-Reply-To: References: <4D9DA400.4060105@behnel.de> <4D9DA560.8070505@behnel.de> <4DB50C05.5060701@behnel.de> <4DB53581.5090505@behnel.de> <4DB53DFE.9060601@behnel.de> <4DC24F3E.5090708@behnel.de> Message-ID: <4DC2BBAE.3040707@behnel.de> Vitja Makarov, 05.05.2011 16:29: > 2011/5/5 Stefan Behnel: >> Vitja Makarov, 05.05.2011 08:41: >>> >>> Recently I've found that pyregr.test_dict (test_mutatingiteration) >>> test makes it slow: >>> >>> def test_mutatingiteration(): >>> d = {} >>> d[1] = 1 >>> for i in d: >>> print i >>> d[i+1] = 1 >>> >>> test_mutatingiteration() >>> >>> >>> In CPython this code raises: RuntimeError: dictionary changed size >>> during iteration >>> And in Cython you have infinite loop. So we can disable this test for now. >> >> Interesting. Yes, if it's a bug in Cython then it's worth disabling the test >> until the bug is fixed. >> >> Anyway, I'll try to come up with a fix quickly. >> > > Cool! It seems that you've fixed the issue and now pyregr takes about > 40 minutes ) Yes. :) I've also disabled a couple of other pyregr tests that took more than one minute due to different reasons. For example, garbage collection tends to take ages towards the end of the test run, when to many modules are loaded. Or the subprocess tests take a while, although they are everything but interesting for Cython. Stefan From d.s.seljebotn at astro.uio.no Thu May 5 20:46:07 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Thu, 05 May 2011 20:46:07 +0200 Subject: [Cython] [SciPy-User] Scikits.sparse build issue In-Reply-To: References: <565dfdb6-56e8-41df-b69f-eaabc02002a7@k22g2000yqh.googlegroups.com> Message-ID: <4DC2F06F.7000006@astro.uio.no> On 05/05/2011 08:42 PM, Nathaniel Smith wrote: > On Thu, May 5, 2011 at 3:03 AM, Anand Patil > wrote: >> >> On May 4, 8:16 pm, Nathaniel Smith wrote: >>> On Tue, May 3, 2011 at 10:10 AM, Nathaniel Smith wrote: >>>> On Tue, May 3, 2011 at 5:51 AM, Anand Patil >>>> wrote: >>>>> scikits/sparse/cholmod.c: In function >>>>> ?__pyx_f_7scikits_6sparse_7cholmod__py_sparse?: >>>>> scikits/sparse/cholmod.c:1713: error: storage size of ?__pyx_t_10? >>>>> isn?t known >>> >>>>> I've never used Cython and am having a hard time figuring this out. >>> >>>> Could you send me the file 'scikits/sparse/cholmod.c'? This means that >>>> there's some C type that was forward-declared, but never actually >>>> defined, and then we tried to instantiate an instance of it. But I'll >>>> need to see the generated code to figure out which type '__pyx_t_10' >>>> is supposed to be. >>> >>> Huh, this appears to be some bad interaction between numpy and cython, >>> rather than anything to do with my code. The offending variable comes >>> from doing 'cimport numpy as np' and then referring to >>> 'np.NPY_F_CONTIGUOUS' -- this is being translated to: >>> enum requirements __pyx_t_10; >>> __pyx_t_10 = NPY_F_CONTIGUOUS; >>> and then gcc is complaining that 'enum requirements' is an undefined type. >>> >>> What version of Numpy and Cython do you have installed? >> >> Cython 0.14.1, Numpy 1.5.1. Which versions do you have? > > It looks like with Cython 0.12.1, which is what I was using before, it > happens not to generate a temporary variable in this case, but Cython > 0.14.1 generates the temporary variable. > > I've just committed a workaround to the scikits.sparse repository: > https://code.google.com/p/scikits-sparse/source/detail?r=ad106e9c2c2d55f2022a3fb8b9282003b55666fc# > (I believe it works -- it does compile -- but technically I can't > guarantee it since for me the tests are now failing with an "illegal > instruction" error inside BLAS. But I think this must be an unrelated > Ubuntu screwup. Yay software.) > > And I'll see about poking Cython upstream to get this fixed... Awh. Thanks! https://github.com/cython/cython/commit/a6ec50077990a9767695896076a8b573a5bdccc0 Dag Sverre From njs at pobox.com Thu May 5 20:58:29 2011 From: njs at pobox.com (Nathaniel Smith) Date: Thu, 5 May 2011 11:58:29 -0700 Subject: [Cython] [SciPy-User] Scikits.sparse build issue In-Reply-To: <4DC2F06F.7000006@astro.uio.no> References: <565dfdb6-56e8-41df-b69f-eaabc02002a7@k22g2000yqh.googlegroups.com> <4DC2F06F.7000006@astro.uio.no> Message-ID: Whoops, looks like we passed each other :-) My patch has a few other fixes you might want to apply too, since I figured I should probably double-check the rest of the 'enum's in there too -- I don't know if they'd cause problems in practice, but... On Thu, May 5, 2011 at 11:46 AM, Dag Sverre Seljebotn wrote: > On 05/05/2011 08:42 PM, Nathaniel Smith wrote: >> >> On Thu, May 5, 2011 at 3:03 AM, Anand Patil >> ?wrote: >>> >>> On May 4, 8:16 pm, Nathaniel Smith ?wrote: >>>> >>>> On Tue, May 3, 2011 at 10:10 AM, Nathaniel Smith ?wrote: >>>>> >>>>> On Tue, May 3, 2011 at 5:51 AM, Anand Patil >>>>> ?wrote: >>>>>> >>>>>> scikits/sparse/cholmod.c: In function >>>>>> ?__pyx_f_7scikits_6sparse_7cholmod__py_sparse?: >>>>>> scikits/sparse/cholmod.c:1713: error: storage size of ?__pyx_t_10? >>>>>> isn?t known >>>> >>>>>> I've never used Cython and am having a hard time figuring this out. >>>> >>>>> Could you send me the file 'scikits/sparse/cholmod.c'? This means that >>>>> there's some C type that was forward-declared, but never actually >>>>> defined, and then we tried to instantiate an instance of it. But I'll >>>>> need to see the generated code to figure out which type '__pyx_t_10' >>>>> is supposed to be. >>>> >>>> Huh, this appears to be some bad interaction between numpy and cython, >>>> rather than anything to do with my code. The offending variable comes >>>> from doing 'cimport numpy as np' and then referring to >>>> 'np.NPY_F_CONTIGUOUS' -- this is being translated to: >>>> ? enum requirements __pyx_t_10; >>>> ? __pyx_t_10 = NPY_F_CONTIGUOUS; >>>> and then gcc is complaining that 'enum requirements' is an undefined >>>> type. >>>> >>>> What version of Numpy and Cython do you have installed? >>> >>> Cython 0.14.1, Numpy 1.5.1. Which versions do you have? >> >> It looks like with Cython 0.12.1, which is what I was using before, it >> happens not to generate a temporary variable in this case, but Cython >> 0.14.1 generates the temporary variable. >> >> I've just committed a workaround to the scikits.sparse repository: >> >> https://code.google.com/p/scikits-sparse/source/detail?r=ad106e9c2c2d55f2022a3fb8b9282003b55666fc# >> (I believe it works -- it does compile -- but technically I can't >> guarantee it since for me the tests are now failing with an "illegal >> instruction" error inside BLAS. But I think this must be an unrelated >> Ubuntu screwup. Yay software.) >> >> And I'll see about poking Cython upstream to get this fixed... > > Awh. Thanks! > > https://github.com/cython/cython/commit/a6ec50077990a9767695896076a8b573a5bdccc0 > > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From d.s.seljebotn at astro.uio.no Thu May 5 21:52:06 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Thu, 05 May 2011 21:52:06 +0200 Subject: [Cython] Git workflow, branches, pull requests Message-ID: <4DC2FFE6.5020409@astro.uio.no> There was just a messup in git history: Mark's OpenMP pull request got merged twice; all commits show up two times. It doesn't matter, since the two openmp branches with the same changes merged OK, but we shouldn't make this a habit. For instance, the openMP commits also show up as part of vitja's pull request, which is confusing. In Mercurial speak: The openmp branch was used like you would use a Mercurial "patch queue" in one case, and as a branch in another case. In git they are the same technically and you rely on conventions to make sure you don't treat a "queue" as a "branch". OPTION A) Either i) only branch from master, or ii) make sure you agree with whoever you're branching from that this is a "branch", not a "patch queue", so that it isn't rebased under your feet. We could also, say, prepend all patch queues with an underscore (its private). OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but nobody are pulling from dagss/cython these days anyway. Opinions? FYI, The workflow me and Mark is currently using is: a) Fork off a feature branch from master (with master I'll always refer to cython/master) b) When one gets in sync with master, do NOT merge master, but rather rebase on top of it: git pull --rebase origin master c) Continue rebasing, and eventually . The advantage of this approach is that ugly merges disappear from history, since commits are rewritten. And the history graph looks very nice and is easy to follow. BUT, if the result is duplication, we should avoid this practice, and rather always merge. Dag Sverre From markflorisson88 at gmail.com Thu May 5 22:09:53 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Thu, 5 May 2011 22:09:53 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC2FFE6.5020409@astro.uio.no> References: <4DC2FFE6.5020409@astro.uio.no> Message-ID: On 5 May 2011 21:52, Dag Sverre Seljebotn wrote: > There was just a messup in git history: Mark's OpenMP pull request got > merged twice; all commits show up two times. > > It doesn't matter, since the two openmp branches with the same changes > merged OK, but we shouldn't make this a habit. For instance, the openMP > commits also show up as part of vitja's pull request, which is confusing. > > In Mercurial speak: The openmp branch was used like you would use a > Mercurial "patch queue" in one case, and as a branch in another case. In git > they are the same technically and you rely on conventions to make sure you > don't treat a "queue" as a "branch". > > OPTION A) Either i) only branch from master, or ii) make sure you agree with > whoever you're branching from that this is a "branch", not a "patch queue", > so that it isn't rebased under your feet. > > We could also, say, prepend all patch queues with an underscore (its > private). > > OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but > nobody are pulling from dagss/cython these days anyway. > > Opinions? > > FYI, > > The workflow me and Mark is currently using is: > > ?a) Fork off a feature branch from master (with master I'll always refer to > cython/master) > > ?b) When one gets in sync with master, do NOT merge master, but rather > rebase on top of it: > > ? ? git pull --rebase origin master > > ?c) Continue rebasing, and eventually . > > The advantage of this approach is that ugly merges disappear from history, > since commits are rewritten. And the history graph looks very nice and is > easy to follow. > > BUT, if the result is duplication, we should avoid this practice, and rather > always merge. > > > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > I think the rebasing is pretty elegant, so I'm +1 on that, as long as everyone agrees because those duplicated commits are nasty. I'm surprised git didn't issue an error to prevent this. From stefan_ml at behnel.de Thu May 5 22:15:55 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 05 May 2011 22:15:55 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> Message-ID: <4DC3057B.4020106@behnel.de> mark florisson, 05.05.2011 22:09: > I think the rebasing is pretty elegant, so I'm +1 on that, as long as > everyone agrees because those duplicated commits are nasty. I'm > surprised git didn't issue an error to prevent this. I'm not surprised at all. Stefan From d.s.seljebotn at astro.uio.no Thu May 5 22:20:00 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Thu, 05 May 2011 22:20:00 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> Message-ID: <4DC30670.9040208@astro.uio.no> On 05/05/2011 10:09 PM, mark florisson wrote: > On 5 May 2011 21:52, Dag Sverre Seljebotn wrote: >> There was just a messup in git history: Mark's OpenMP pull request got >> merged twice; all commits show up two times. >> >> It doesn't matter, since the two openmp branches with the same changes >> merged OK, but we shouldn't make this a habit. For instance, the openMP >> commits also show up as part of vitja's pull request, which is confusing. >> >> In Mercurial speak: The openmp branch was used like you would use a >> Mercurial "patch queue" in one case, and as a branch in another case. In git >> they are the same technically and you rely on conventions to make sure you >> don't treat a "queue" as a "branch". >> >> OPTION A) Either i) only branch from master, or ii) make sure you agree with >> whoever you're branching from that this is a "branch", not a "patch queue", >> so that it isn't rebased under your feet. >> >> We could also, say, prepend all patch queues with an underscore (its >> private). >> >> OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but >> nobody are pulling from dagss/cython these days anyway. >> >> Opinions? >> >> FYI, >> >> The workflow me and Mark is currently using is: >> >> a) Fork off a feature branch from master (with master I'll always refer to >> cython/master) >> >> b) When one gets in sync with master, do NOT merge master, but rather >> rebase on top of it: >> >> git pull --rebase origin master >> >> c) Continue rebasing, and eventually . >> >> The advantage of this approach is that ugly merges disappear from history, >> since commits are rewritten. And the history graph looks very nice and is >> easy to follow. >> >> BUT, if the result is duplication, we should avoid this practice, and rather >> always merge. >> >> >> Dag Sverre > > I think the rebasing is pretty elegant, so I'm +1 on that, as long as > everyone agrees because those duplicated commits are nasty. I'm > surprised git didn't issue an error to prevent this. Going OT: I guess a principle of git is to be as dumb as possible, so that you can predict what it does. When you rebase, you really get entirely new versions of all your commits. There's no way to link the old commits with the new commits, except to compare the commit message. And not even that, since you can change commit messages during rebases. Git doesn't even store commits by their diff, it stores each commit by the resulting full tree contents, so even if the patch is the exact same, git couldn't really know (without going through your entire history and check for "similar changes"...ugh) What I wish they did was to add a simple "rebased-from" header field on commits, which could be trivially checked on merges to issue a warning. I guess the reason it is not there is because usually you're about to (automatically) throw away the commits, so the only purpose it would have would be sort of pedagogical. Dag Sverre From stefan_ml at behnel.de Thu May 5 22:22:25 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 05 May 2011 22:22:25 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC2FFE6.5020409@astro.uio.no> References: <4DC2FFE6.5020409@astro.uio.no> Message-ID: <4DC30701.3070304@behnel.de> Dag Sverre Seljebotn, 05.05.2011 21:52: > There was just a messup in git history: Mark's OpenMP pull request got > merged twice; all commits show up two times. What (I think) happened, was that Vitja pulled in Mark's changes into his unreachable code removal branch, and they ended up in his pull request. I guess I was assuming that git wouldn't care too much about branch duplication, so I just accepted the pull request via the web interface. Apparently, it did care. I tend to rebase my local change sets before pushing them, and I think it makes sense to continue doing that. Stefan From markflorisson88 at gmail.com Thu May 5 22:30:49 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Thu, 5 May 2011 22:30:49 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC30701.3070304@behnel.de> References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: On 5 May 2011 22:22, Stefan Behnel wrote: > Dag Sverre Seljebotn, 05.05.2011 21:52: >> >> There was just a messup in git history: Mark's OpenMP pull request got >> merged twice; all commits show up two times. > > What (I think) happened, was that Vitja pulled in Mark's changes into his > unreachable code removal branch, and they ended up in his pull request. I > guess I was assuming that git wouldn't care too much about branch > duplication, so I just accepted the pull request via the web interface. > Apparently, it did care. > > I tend to rebase my local change sets before pushing them, and I think it > makes sense to continue doing that. > > Stefan > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > Whatever approach we take, it should be documented extensively on the hackerguide, at least the rebase approach, as it has apparently somewhat catastrophic results if not everyone does it. On the one hand rebasing gives you a nice history, but on the other hand it's also a bit harder to use and if you start merging at some point reverting to rebasing is not so easy. So perhaps we should just ignore the 'merge' commits (using command line git, git log --no-merges) and pull and push away. From robertwb at math.washington.edu Thu May 5 22:49:28 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Thu, 5 May 2011 13:49:28 -0700 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC30701.3070304@behnel.de> References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel wrote: > Dag Sverre Seljebotn, 05.05.2011 21:52: >> >> There was just a messup in git history: Mark's OpenMP pull request got >> merged twice; all commits show up two times. > > What (I think) happened, was that Vitja pulled in Mark's changes into his > unreachable code removal branch, and they ended up in his pull request. I > guess I was assuming that git wouldn't care too much about branch > duplication, so I just accepted the pull request via the web interface. > Apparently, it did care. > > I tend to rebase my local change sets before pushing them, and I think it > makes sense to continue doing that. +1, I think for as-yet-unpublished changes, it makes the most sense to rebase, but for a longer-term branch, merging isn't as disruptive to the history (in fact is probably more reflective of what's going on) and is much better than duplication. To clarify, is this only a problem when we have A cloned from master B cloned from A (or from master and then pulls in A) A rebases A+B merged into master ? If this is the case, then we could simply make the rule that you should ask before hacking a clone atop anything but master. (Multiple people can share a repeatedly-rebased branch, right.) We could also us the underscore (or another) convention to mean "this branch is being used as a queue, puller beware." Surely other projects have dealt with this. - Robert From d.s.seljebotn at astro.uio.no Thu May 5 23:03:29 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Thu, 05 May 2011 23:03:29 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: Yes, that is the only time it happens. Do we agree on a) ask before you pull anything that is not in cython/* (ie in private repos), b) document it in hackerguide? DS -- Sent from my Android phone with K-9 Mail. Please excuse my brevity. Robert Bradshaw wrote: On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel wrote: > Dag Sverre Seljebotn, 05.05.2011 21:52: >> >> There was just a messup in git history: Mark's OpenMP pull request got >> merged twice; all commits show up two times. > > What (I think) happened, was that Vitja pulled in Mark's changes into his > unreachable code removal branch, and they ended up in his pull request. I > guess I was assuming that git wouldn't care too much about branch > duplication, so I just accepted the pull request via the web interface. > Apparently, it did care. > > I tend to rebase my local change sets before pushing them, and I think it > makes sense to continue doing that. +1, I think for as-yet-unpublished changes, it makes the most sense to rebase, but for a longer-term branch, merging isn't as disruptive to the history (in fact is probably more reflective of what's going on) and is much better than duplication. To clarify, is this only a problem when we have A cloned from master B cloned from A (or from master and then pulls in A) A rebases A+B merged into master ? If this is the case, then we could simply make the rule that you should ask before hacking a clone atop anything but master. (Multiple people can share a repeatedly-rebased branch, right.) We could also us the underscore (or another) convention to mean "this branch is being used as a queue, puller beware." Surely other projects have dealt with this. - Robert_____________________________________________ cython-devel mailing list cython-devel at python.org http://mail.python.org/mailman/listinfo/cython-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From robertwb at math.washington.edu Thu May 5 23:07:50 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Thu, 5 May 2011 14:07:50 -0700 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: I don't like the default to be "don't pull from me"--I'd rather there be some convention to indicate a branch is being used as a queue. Maybe even foo-queue, or a leading underscore if people like that. On Thu, May 5, 2011 at 2:03 PM, Dag Sverre Seljebotn wrote: > Yes, that is the only time it happens. > > Do we agree on a) ask before you pull anything that is not in cython/* (ie > in private repos), b) document it in hackerguide? > > DS > > > -- > Sent from my Android phone with K-9 Mail. Please excuse my brevity. > > Robert Bradshaw wrote: >> >> On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel wrote: >> > Dag Sverre Seljebotn, 05.05.2011 21:52: >> >> There was just a messup in >> git history: Mark's OpenMP pull request got >> merged twice; all commits >> show up two times. > > What (I think) happened, was that Vitja pulled in >> Mark's changes into his > unreachable code removal branch, and they ended up >> in his pull request. I > guess I was assuming that git wouldn't care too >> much about branch > duplication, so I just accepted the pull request via the >> web interface. > Apparently, it did care. > > I tend to rebase my local >> change sets before pushing them, and I think it > makes sense to continue >> doing that. +1, I think for as-yet-unpublished changes, it makes the most >> sense to rebase, but for a longer-term branch, merging isn't as disruptive >> to the history (in fact is probably more reflective of what's going on) and >> is much better than duplication. To clarify, is this only a problem when we >> have A cloned from master B cloned from A (or from master and then pulls in >> A) A rebases A+B merged into master ? If this is the case, then we could >> simply make the rule that you should ask before hacking a clone atop >> anything but master. (Multiple people can share a repeatedly-rebased branch, >> right.) We could also us the underscore (or another) convention to mean >> "this branch is being used as a queue, puller beware." Surely other projects >> have dealt with this. - Robert >> ________________________________ >> cython-devel mailing list cython-devel at python.org >> http://mail.python.org/mailman/listinfo/cython-devel > > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > > From vitja.makarov at gmail.com Fri May 6 08:20:22 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Fri, 6 May 2011 10:20:22 +0400 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: 2011/5/6 Robert Bradshaw : > I don't like the default to be "don't pull from me"--I'd rather there > be some convention to indicate a branch is being used as a queue. > Maybe even foo-queue, or a leading underscore if people like that. > > On Thu, May 5, 2011 at 2:03 PM, Dag Sverre Seljebotn > wrote: >> Yes, that is the only time it happens. >> >> Do we agree on a) ask before you pull anything that is not in cython/* (ie >> in private repos), b) document it in hackerguide? >> >> DS >> >> >> -- >> Sent from my Android phone with K-9 Mail. Please excuse my brevity. >> >> Robert Bradshaw wrote: >>> >>> On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel wrote: >>> > Dag Sverre Seljebotn, 05.05.2011 21:52: >> >> There was just a messup in >>> git history: Mark's OpenMP pull request got >> merged twice; all commits >>> show up two times. > > What (I think) happened, was that Vitja pulled in >>> Mark's changes into his > unreachable code removal branch, and they ended up >>> in his pull request. I > guess I was assuming that git wouldn't care too >>> much about branch > duplication, so I just accepted the pull request via the >>> web interface. > Apparently, it did care. > > I tend to rebase my local >>> change sets before pushing them, and I think it > makes sense to continue >>> doing that. +1, I think for as-yet-unpublished changes, it makes the most >>> sense to rebase, but for a longer-term branch, merging isn't as disruptive >>> to the history (in fact is probably more reflective of what's going on) and >>> is much better than duplication. To clarify, is this only a problem when we >>> have A cloned from master B cloned from A (or from master and then pulls in >>> A) A rebases A+B merged into master ? If this is the case, then we could >>> simply make the rule that you should ask before hacking a clone atop >>> anything but master. (Multiple people can share a repeatedly-rebased branch, >>> right.) We could also us the underscore (or another) convention to mean >>> "this branch is being used as a queue, puller beware." Surely other projects >>> have dealt with this. - Robert About my branch: I've rebased it from upstream/master at home and made "forced push" At work I pulled it back and rebased from origin, then I tried to rebase if again from upstream/master Guess I was wrong somewhere. So I've lost two latest commits (generators related fix) Sometimes it's much easy to branch from upstream and then make cherry-pick (manual rebase). -- vitja. From d.s.seljebotn at astro.uio.no Fri May 6 08:41:42 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 06 May 2011 08:41:42 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: <4DC39826.4060109@astro.uio.no> On 05/06/2011 08:20 AM, Vitja Makarov wrote: > 2011/5/6 Robert Bradshaw: >> I don't like the default to be "don't pull from me"--I'd rather there >> be some convention to indicate a branch is being used as a queue. >> Maybe even foo-queue, or a leading underscore if people like that. >> >> On Thu, May 5, 2011 at 2:03 PM, Dag Sverre Seljebotn >> wrote: >>> Yes, that is the only time it happens. >>> >>> Do we agree on a) ask before you pull anything that is not in cython/* (ie >>> in private repos), b) document it in hackerguide? >>> >>> DS >>> >>> >>> -- >>> Sent from my Android phone with K-9 Mail. Please excuse my brevity. >>> >>> Robert Bradshaw wrote: >>>> >>>> On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel wrote: >>>>> Dag Sverre Seljebotn, 05.05.2011 21:52:>> >> There was just a messup in >>>> git history: Mark's OpenMP pull request got>> merged twice; all commits >>>> show up two times.> > What (I think) happened, was that Vitja pulled in >>>> Mark's changes into his> unreachable code removal branch, and they ended up >>>> in his pull request. I> guess I was assuming that git wouldn't care too >>>> much about branch> duplication, so I just accepted the pull request via the >>>> web interface.> Apparently, it did care.> > I tend to rebase my local >>>> change sets before pushing them, and I think it> makes sense to continue >>>> doing that. +1, I think for as-yet-unpublished changes, it makes the most >>>> sense to rebase, but for a longer-term branch, merging isn't as disruptive >>>> to the history (in fact is probably more reflective of what's going on) and >>>> is much better than duplication. To clarify, is this only a problem when we >>>> have A cloned from master B cloned from A (or from master and then pulls in >>>> A) A rebases A+B merged into master ? If this is the case, then we could >>>> simply make the rule that you should ask before hacking a clone atop >>>> anything but master. (Multiple people can share a repeatedly-rebased branch, >>>> right.) We could also us the underscore (or another) convention to mean >>>> "this branch is being used as a queue, puller beware." Surely other projects >>>> have dealt with this. - Robert > > > About my branch: > > I've rebased it from upstream/master at home and made "forced push" > At work I pulled it back and rebased from origin, then I tried to > rebase if again from upstream/master Do I understand correctly that you: a) You make local changes at home b) Rebase them on cython/master c) Force-push to vitja/somebranch d) Go to work, where you have other local changes e) Rebase your work changes at work on top of vitja/somebranch If this is correct; then this can't work. The reason is that after the force-push in c), there are no shared commits (apart from what's shared from cython/master) between your work computer and vitja/somebranch. So the rule is: If you rebase a branch, then if you have other copies of that branch (like on a work computer), destroy them (e.g., git branch -D)! And then fetch new copies of the branches. (And as you say, if you do have different changes in many places then you can recover from an unfortunate rebase by cherry-picking. And you can always undo a rebase by looking at "git reflog" and manually check out the old HEAD.) Dag Sverre From d.s.seljebotn at astro.uio.no Fri May 6 09:14:28 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 06 May 2011 09:14:28 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: <4DC39FD4.1030301@astro.uio.no> On 05/05/2011 11:07 PM, Robert Bradshaw wrote: > I don't like the default to be "don't pull from me"--I'd rather there > be some convention to indicate a branch is being used as a queue. > Maybe even foo-queue, or a leading underscore if people like that. I've seen leading underscore being used by other people on github, so let's settle on that for now. Of course, if you do pull from a non-master branch, you should be communicating a lot about that fact anyway; it's a bad idea for a lot of other reasons as well. I've updated http://wiki.cython.org/HackerGuide. Here's an example of prior art in git workflows, developed I think primarily for IPython: https://github.com/matthew-brett/gitwash It's essentially some Sphinx documentation with replacable names ("To contribute to PROJECTNAME, you should get an account on github...") that one can merge into ones own documentation. If anybody is interested in looking at that I'm all for it. Dag Sverre From d.s.seljebotn at astro.uio.no Fri May 6 09:16:02 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 06 May 2011 09:16:02 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC39FD4.1030301@astro.uio.no> References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> <4DC39FD4.1030301@astro.uio.no> Message-ID: <4DC3A032.10402@astro.uio.no> On 05/06/2011 09:14 AM, Dag Sverre Seljebotn wrote: > On 05/05/2011 11:07 PM, Robert Bradshaw wrote: >> I don't like the default to be "don't pull from me"--I'd rather there >> be some convention to indicate a branch is being used as a queue. >> Maybe even foo-queue, or a leading underscore if people like that. > > I've seen leading underscore being used by other people on github, so > let's settle on that for now. > > Of course, if you do pull from a non-master branch, you should be > communicating a lot about that fact anyway; it's a bad idea for a lot of > other reasons as well. > > I've updated http://wiki.cython.org/HackerGuide. > > Here's an example of prior art in git workflows, developed I think > primarily for IPython: > > https://github.com/matthew-brett/gitwash > > It's essentially some Sphinx documentation with replacable names ("To > contribute to PROJECTNAME, you should get an account on github...") that > one can merge into ones own documentation. If anybody is interested in > looking at that I'm all for it. Here's an example of resulting docs from "gitwash-dumper.py": http://nipy.sourceforge.net/nipy/stable/devel/guidelines/gitwash/index.html DS From vitja.makarov at gmail.com Fri May 6 09:24:40 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Fri, 6 May 2011 11:24:40 +0400 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC39826.4060109@astro.uio.no> References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> <4DC39826.4060109@astro.uio.no> Message-ID: 2011/5/6 Dag Sverre Seljebotn : > On 05/06/2011 08:20 AM, Vitja Makarov wrote: >> >> 2011/5/6 Robert Bradshaw: >>> >>> I don't like the default to be "don't pull from me"--I'd rather there >>> be some convention to indicate a branch is being used as a queue. >>> Maybe even foo-queue, or a leading underscore if people like that. >>> >>> On Thu, May 5, 2011 at 2:03 PM, Dag Sverre Seljebotn >>> ?wrote: >>>> >>>> Yes, that is the only time it happens. >>>> >>>> Do we agree on a) ask before you pull anything that is not in cython/* >>>> (ie >>>> in private repos), b) document it in hackerguide? >>>> >>>> DS >>>> >>>> >>>> -- >>>> Sent from my Android phone with K-9 Mail. Please excuse my brevity. >>>> >>>> Robert Bradshaw ?wrote: >>>>> >>>>> On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel >>>>> ?wrote: >>>>>> >>>>>> Dag Sverre Seljebotn, 05.05.2011 21:52:>> ?>> ?There was just a messup >>>>>> in >>>>> >>>>> git history: Mark's OpenMP pull request got>> ?merged twice; all >>>>> commits >>>>> show up two times.> ?> ?What (I think) happened, was that Vitja pulled >>>>> in >>>>> Mark's changes into his> ?unreachable code removal branch, and they >>>>> ended up >>>>> in his pull request. I> ?guess I was assuming that git wouldn't care >>>>> too >>>>> much about branch> ?duplication, so I just accepted the pull request >>>>> via the >>>>> web interface.> ?Apparently, it did care.> ?> ?I tend to rebase my >>>>> local >>>>> change sets before pushing them, and I think it> ?makes sense to >>>>> continue >>>>> doing that. +1, I think for as-yet-unpublished changes, it makes the >>>>> most >>>>> sense to rebase, but for a longer-term branch, merging isn't as >>>>> disruptive >>>>> to the history (in fact is probably more reflective of what's going on) >>>>> and >>>>> is much better than duplication. To clarify, is this only a problem >>>>> when we >>>>> have A cloned from master B cloned from A (or from master and then >>>>> pulls in >>>>> A) A rebases A+B merged into master ? If this is the case, then we >>>>> could >>>>> simply make the rule that you should ask before hacking a clone atop >>>>> anything but master. (Multiple people can share a repeatedly-rebased >>>>> branch, >>>>> right.) We could also us the underscore (or another) convention to mean >>>>> "this branch is being used as a queue, puller beware." Surely other >>>>> projects >>>>> have dealt with this. - Robert >> >> >> About my branch: >> >> I've rebased it from upstream/master at home and made "forced push" >> At work I pulled it back and rebased from origin, then I tried to >> rebase if again from upstream/master > > Do I understand correctly that you: > > ?a) You make local changes at home > ?b) Rebase them on cython/master > ?c) Force-push to vitja/somebranch > ?d) Go to work, where you have other local changes > ?e) Rebase your work changes at work on top of vitja/somebranch > Right. > If this is correct; then this can't work. The reason is that after the > force-push in c), there are no shared commits (apart from what's shared from > cython/master) between your work computer and vitja/somebranch. > > So the rule is: If you rebase a branch, then if you have other copies of > that branch (like on a work computer), destroy them (e.g., git branch -D)! > ?And then fetch new copies of the branches. > > (And as you say, if you do have different changes in many places then you > can recover from an unfortunate rebase by cherry-picking. And you can always > undo a rebase by looking at "git reflog" and manually check out the old > HEAD.) > Thank you for explanation. So btw, when I do rebase and my changes were already pushed I have to use forced push. Is forced push ok? -- vitja. From d.s.seljebotn at astro.uio.no Fri May 6 09:32:58 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 06 May 2011 09:32:58 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> <4DC39826.4060109@astro.uio.no> Message-ID: <4DC3A42A.2090705@astro.uio.no> On 05/06/2011 09:24 AM, Vitja Makarov wrote: > 2011/5/6 Dag Sverre Seljebotn: >> On 05/06/2011 08:20 AM, Vitja Makarov wrote: >>> >>> 2011/5/6 Robert Bradshaw: >>>> >>>> I don't like the default to be "don't pull from me"--I'd rather there >>>> be some convention to indicate a branch is being used as a queue. >>>> Maybe even foo-queue, or a leading underscore if people like that. >>>> >>>> On Thu, May 5, 2011 at 2:03 PM, Dag Sverre Seljebotn >>>> wrote: >>>>> >>>>> Yes, that is the only time it happens. >>>>> >>>>> Do we agree on a) ask before you pull anything that is not in cython/* >>>>> (ie >>>>> in private repos), b) document it in hackerguide? >>>>> >>>>> DS >>>>> >>>>> >>>>> -- >>>>> Sent from my Android phone with K-9 Mail. Please excuse my brevity. >>>>> >>>>> Robert Bradshaw wrote: >>>>>> >>>>>> On Thu, May 5, 2011 at 1:22 PM, Stefan Behnel >>>>>> wrote: >>>>>>> >>>>>>> Dag Sverre Seljebotn, 05.05.2011 21:52:>> >> There was just a messup >>>>>>> in >>>>>> >>>>>> git history: Mark's OpenMP pull request got>> merged twice; all >>>>>> commits >>>>>> show up two times.> > What (I think) happened, was that Vitja pulled >>>>>> in >>>>>> Mark's changes into his> unreachable code removal branch, and they >>>>>> ended up >>>>>> in his pull request. I> guess I was assuming that git wouldn't care >>>>>> too >>>>>> much about branch> duplication, so I just accepted the pull request >>>>>> via the >>>>>> web interface.> Apparently, it did care.> > I tend to rebase my >>>>>> local >>>>>> change sets before pushing them, and I think it> makes sense to >>>>>> continue >>>>>> doing that. +1, I think for as-yet-unpublished changes, it makes the >>>>>> most >>>>>> sense to rebase, but for a longer-term branch, merging isn't as >>>>>> disruptive >>>>>> to the history (in fact is probably more reflective of what's going on) >>>>>> and >>>>>> is much better than duplication. To clarify, is this only a problem >>>>>> when we >>>>>> have A cloned from master B cloned from A (or from master and then >>>>>> pulls in >>>>>> A) A rebases A+B merged into master ? If this is the case, then we >>>>>> could >>>>>> simply make the rule that you should ask before hacking a clone atop >>>>>> anything but master. (Multiple people can share a repeatedly-rebased >>>>>> branch, >>>>>> right.) We could also us the underscore (or another) convention to mean >>>>>> "this branch is being used as a queue, puller beware." Surely other >>>>>> projects >>>>>> have dealt with this. - Robert >>> >>> >>> About my branch: >>> >>> I've rebased it from upstream/master at home and made "forced push" >>> At work I pulled it back and rebased from origin, then I tried to >>> rebase if again from upstream/master >> >> Do I understand correctly that you: >> >> a) You make local changes at home >> b) Rebase them on cython/master >> c) Force-push to vitja/somebranch >> d) Go to work, where you have other local changes >> e) Rebase your work changes at work on top of vitja/somebranch >> > > > Right. > >> If this is correct; then this can't work. The reason is that after the >> force-push in c), there are no shared commits (apart from what's shared from >> cython/master) between your work computer and vitja/somebranch. >> >> So the rule is: If you rebase a branch, then if you have other copies of >> that branch (like on a work computer), destroy them (e.g., git branch -D)! >> And then fetch new copies of the branches. >> >> (And as you say, if you do have different changes in many places then you >> can recover from an unfortunate rebase by cherry-picking. And you can always >> undo a rebase by looking at "git reflog" and manually check out the old >> HEAD.) >> > > Thank you for explanation. > > So btw, when I do rebase and my changes were already pushed I have to > use forced push. > Is forced push ok? Forced push is trivially OK if the commits you are "overwriting" has not been fetched anywhere else (or, you plan to immediately erase them at their other location). Otherwise, you really need to pay attention. In general, if you make the following cycle "atomic", you're OK: - Fetch branch from github - Make some commits - Force-push back to github However, if you interrupt the cycle in the middle, you'll need to spend time to recover from your "race" :-) Here's a similar question which lists some convenient commands: http://stackoverflow.com/questions/3815193/how-can-i-safely-use-git-rebase-when-working-on-multiple-computers (Although I'm not sure if I recommend getting into the habit of doing "git push -f", just typing "git push -f origin mybranch" seems a lot safer.) Dag Sverre From yury at shurup.com Fri May 6 09:33:37 2011 From: yury at shurup.com (Yury V. Zaytsev) Date: Fri, 06 May 2011 09:33:37 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DC30701.3070304@behnel.de> Message-ID: <1304667217.2482.11.camel@newpride> On Thu, 2011-05-05 at 13:49 -0700, Robert Bradshaw wrote: > Surely other projects have dealt with this. We have for instance adopted a very strict set of policies on that: 1) Never branch of anything except for master or x.y.z-stable branches 2) Never rebase master or x.y.z-stable branches, unless everybody agrees 3) Never do fast-forward merges, always rebase your stuff before merge 4) Never commit directly to master, use feature branches That is, all branches are either in the personal namespace of the developers for experimental stuff, or in the main namespace prefixed with the ticket number. I admit that this is quite restrictive, but in the end, it doesn't take so much effort to follow and the history is very nice and easy to understand, I even literally follow the development by reading the history, when I am unable to track IRC etc. Of course, you don't have to copy this blindly, but few permissive conventions, which do not impose additional load on the developers like 1) Always branch from master 2) Never rebase master would definitively not hurt. I was recently trying to bisect Cython, as I was under impression that recent commits broke something for me (it turned out not to be the case, but that's not the point) and the history is just to horribly confusing that I couldn't make any sense out of it. All these branches from branches from branches which gets merged in random order make it impossible for an outside person to make any sensible use of this information... Hope that helps, -- Sincerely yours, Yury V. Zaytsev From vitja.makarov at gmail.com Mon May 9 09:29:52 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 9 May 2011 11:29:52 +0400 Subject: [Cython] buffers and flow-control Message-ID: I've never been using buffers so my question is: Should uninitialized buffer access raise UnboundLocalVariable error? Like this: def foo(): cdef object bar print bar -- vitja. From d.s.seljebotn at astro.uio.no Mon May 9 10:01:18 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Mon, 09 May 2011 10:01:18 +0200 Subject: [Cython] buffers and flow-control In-Reply-To: References: Message-ID: <4DC79F4E.1050200@astro.uio.no> On 05/09/2011 09:29 AM, Vitja Makarov wrote: > I've never been using buffers so my question is: > > Should uninitialized buffer access raise UnboundLocalVariable error? > > Like this: > > def foo(): > cdef object bar > print bar > "object[int]" should behave exactly the same way as "object" does during control flow analysis. Dag Sverre From matej at laitl.cz Wed May 11 22:27:30 2011 From: matej at laitl.cz (=?utf-8?q?Mat=C4=9Bj_Laitl?=) Date: Wed, 11 May 2011 22:27:30 +0200 Subject: [Cython] Buffer type specification (CEP 514) in @cython.locals() in .pxd Message-ID: <201105112227.31425.matej@laitl.cz> Hi list, it has been unusually quiet here so it's time to speak up. How hard would it be to implement support for specifying buffer dtype (and friends) in @cython.locals() in a .pxd file? Following code (in a .pxd file) cimport numpy @cython.locals(local1 = numpy.ndarray[double]) cdef double f() currently yields "test.pxd:4:32: Not a type" error. The problem is that one currently cannot make use of buffer access optimisation for local variables in pure python mode. I use pure mode extensively in my project [1]. [1] https://github.com/strohel/PyBayes I understand that it has no sense in .py files as type type is not usually subscriptable. On the same note, is there a plan to implement fast buffer access for class variables? ;) (this is obviously not that crucial) Regards and keep up the good work! Mat?j Laitl From ondrej at certik.cz Fri May 13 00:36:47 2011 From: ondrej at certik.cz (Ondrej Certik) Date: Thu, 12 May 2011 15:36:47 -0700 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DC2FFE6.5020409@astro.uio.no> References: <4DC2FFE6.5020409@astro.uio.no> Message-ID: Hi, On Thu, May 5, 2011 at 12:52 PM, Dag Sverre Seljebotn wrote: > There was just a messup in git history: Mark's OpenMP pull request got > merged twice; all commits show up two times. > > It doesn't matter, since the two openmp branches with the same changes > merged OK, but we shouldn't make this a habit. For instance, the openMP > commits also show up as part of vitja's pull request, which is confusing. > > In Mercurial speak: The openmp branch was used like you would use a > Mercurial "patch queue" in one case, and as a branch in another case. In git > they are the same technically and you rely on conventions to make sure you > don't treat a "queue" as a "branch". > > OPTION A) Either i) only branch from master, or ii) make sure you agree with > whoever you're branching from that this is a "branch", not a "patch queue", > so that it isn't rebased under your feet. > > We could also, say, prepend all patch queues with an underscore (its > private). > > OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but > nobody are pulling from dagss/cython these days anyway. What about: OPTION C) The one who pushes things into the master knows master enough to see whether or not it makes sense to merge this, or if it was already in, he/she will simply comment into the pull request and close it manually Ondrej From d.s.seljebotn at astro.uio.no Fri May 13 08:34:38 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 13 May 2011 08:34:38 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> Message-ID: <4DCCD0FE.3090402@astro.uio.no> On 05/13/2011 12:36 AM, Ondrej Certik wrote: > Hi, > > On Thu, May 5, 2011 at 12:52 PM, Dag Sverre Seljebotn > wrote: >> There was just a messup in git history: Mark's OpenMP pull request got >> merged twice; all commits show up two times. >> >> It doesn't matter, since the two openmp branches with the same changes >> merged OK, but we shouldn't make this a habit. For instance, the openMP >> commits also show up as part of vitja's pull request, which is confusing. >> >> In Mercurial speak: The openmp branch was used like you would use a >> Mercurial "patch queue" in one case, and as a branch in another case. In git >> they are the same technically and you rely on conventions to make sure you >> don't treat a "queue" as a "branch". >> >> OPTION A) Either i) only branch from master, or ii) make sure you agree with >> whoever you're branching from that this is a "branch", not a "patch queue", >> so that it isn't rebased under your feet. >> >> We could also, say, prepend all patch queues with an underscore (its >> private). >> >> OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but >> nobody are pulling from dagss/cython these days anyway. > > What about: > > OPTION C) The one who pushes things into the master knows master > enough to see whether or not it makes sense to merge this, or if it > was already in, he/she will simply comment into the pull request and > close it manually This doesn't make sense to me. Are you sure you read the scenario correctly? Dag Sverre From ondrej at certik.cz Fri May 13 09:05:45 2011 From: ondrej at certik.cz (Ondrej Certik) Date: Fri, 13 May 2011 00:05:45 -0700 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: <4DCCD0FE.3090402@astro.uio.no> References: <4DC2FFE6.5020409@astro.uio.no> <4DCCD0FE.3090402@astro.uio.no> Message-ID: On Thu, May 12, 2011 at 11:34 PM, Dag Sverre Seljebotn wrote: > On 05/13/2011 12:36 AM, Ondrej Certik wrote: >> >> Hi, >> >> On Thu, May 5, 2011 at 12:52 PM, Dag Sverre Seljebotn >> ?wrote: >>> >>> There was just a messup in git history: Mark's OpenMP pull request got >>> merged twice; all commits show up two times. >>> >>> It doesn't matter, since the two openmp branches with the same changes >>> merged OK, but we shouldn't make this a habit. For instance, the openMP >>> commits also show up as part of vitja's pull request, which is confusing. >>> >>> In Mercurial speak: The openmp branch was used like you would use a >>> Mercurial "patch queue" in one case, and as a branch in another case. In >>> git >>> they are the same technically and you rely on conventions to make sure >>> you >>> don't treat a "queue" as a "branch". >>> >>> OPTION A) Either i) only branch from master, or ii) make sure you agree >>> with >>> whoever you're branching from that this is a "branch", not a "patch >>> queue", >>> so that it isn't rebased under your feet. >>> >>> We could also, say, prepend all patch queues with an underscore (its >>> private). >>> >>> OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but >>> nobody are pulling from dagss/cython these days anyway. >> >> What about: >> >> OPTION C) The one who pushes things into the master knows master >> enough to see whether or not it makes sense to merge this, or if it >> was already in, he/she will simply comment into the pull request and >> close it manually > > This doesn't make sense to me. Are you sure you read the scenario correctly? You wrote: " There was just a messup in git history: Mark's OpenMP pull request got merged twice; all commits show up two times. " So somebody pushed in Marks' patches twice. My OPTION C) is that the one, who pushes patches in is responsible to make sure that they only get pushed in once. That's what we do in sympy, we don't have any formal option A or B, but people with push access must prove that they are capable of using git, and not breaking (or messing up) things. Of course, everybody can make a mistake though. It seems to be working just great, so I just wanted to share our experience. Let me know what doesn't make sense. Ondrej From d.s.seljebotn at astro.uio.no Fri May 13 09:18:35 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 13 May 2011 09:18:35 +0200 Subject: [Cython] Git workflow, branches, pull requests In-Reply-To: References: <4DC2FFE6.5020409@astro.uio.no> <4DCCD0FE.3090402@astro.uio.no> Message-ID: <4DCCDB4B.8090104@astro.uio.no> On 05/13/2011 09:05 AM, Ondrej Certik wrote: > On Thu, May 12, 2011 at 11:34 PM, Dag Sverre Seljebotn > wrote: >> On 05/13/2011 12:36 AM, Ondrej Certik wrote: >>> >>> Hi, >>> >>> On Thu, May 5, 2011 at 12:52 PM, Dag Sverre Seljebotn >>> wrote: >>>> >>>> There was just a messup in git history: Mark's OpenMP pull request got >>>> merged twice; all commits show up two times. >>>> >>>> It doesn't matter, since the two openmp branches with the same changes >>>> merged OK, but we shouldn't make this a habit. For instance, the openMP >>>> commits also show up as part of vitja's pull request, which is confusing. >>>> >>>> In Mercurial speak: The openmp branch was used like you would use a >>>> Mercurial "patch queue" in one case, and as a branch in another case. In >>>> git >>>> they are the same technically and you rely on conventions to make sure >>>> you >>>> don't treat a "queue" as a "branch". >>>> >>>> OPTION A) Either i) only branch from master, or ii) make sure you agree >>>> with >>>> whoever you're branching from that this is a "branch", not a "patch >>>> queue", >>>> so that it isn't rebased under your feet. >>>> >>>> We could also, say, prepend all patch queues with an underscore (its >>>> private). >>>> >>>> OPTION B) Stop rebasing. I'd have a very hard time doing that myself, but >>>> nobody are pulling from dagss/cython these days anyway. >>> >>> What about: >>> >>> OPTION C) The one who pushes things into the master knows master >>> enough to see whether or not it makes sense to merge this, or if it >>> was already in, he/she will simply comment into the pull request and >>> close it manually >> >> This doesn't make sense to me. Are you sure you read the scenario correctly? > > You wrote: > > " > There was just a messup in git history: Mark's OpenMP pull request got > merged twice; all commits show up two times. > " > > So somebody pushed in Marks' patches twice. My OPTION C) is that the > one, who pushes patches in is responsible to make sure that they only > get pushed in once. > > That's what we do in sympy, we don't have any formal option A or B, > but people with push access must prove that they are capable of using > git, and not breaking (or messing up) things. Of course, everybody can > make a mistake though. > > It seems to be working just great, so I just wanted to share our > experience. Let me know what doesn't make sense. Ah ok. So in this case, the reviewer would have to request that the second pull request was fixed/rebased. I guess that is still the safety mechanism, but it's nice to also discuss how to not get into those situations. I'm not saying that there will be serious repercussions if one doesn't follow the rules, I was more talking guidelines for not getting into trouble without having to learn all of git. Note that a big part of this thread was to actually make sure everybody (in particular the core devs) knew about how Git rebasing works. The mistake was made in the first place because the reviewer assumed that "git will figure this out". Keep in mind that we just switched, and I think some core devs are still using hg-git, for instance. Dag Sverre From stefan_ml at behnel.de Thu May 19 21:35:17 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 19 May 2011 21:35:17 +0200 Subject: [Cython] Specializing str methods? In-Reply-To: <4DD542B4.1070802@wingware.com> References: <4DA4D997.7050709@wingware.com> <4DA51ECA.1090603@behnel.de> <4DA53920.8040000@behnel.de> <4DA5BCEA.8030501@wingware.com> <4DA5BFEA.8050001@behnel.de> <4DD542B4.1070802@wingware.com> Message-ID: <4DD570F5.9050306@behnel.de> Hi, the right place to discuss this is the cython-devel mailing list. John Ehresman, 19.05.2011 18:17: > On 4/13/11 11:23 AM, Stefan Behnel wrote: >> You can add BuiltinMethod entries for the "str" type in Builtin.py and >> map them to a function name like "__Pyx_Str_PyString_WhatEver()". Then, >> define "utility_code" code blocks for each of the methods that #defines >> that name to the appropriate PyString_*() or PyUnicode_*() C-API >> function, depending on the Python version it runs with. There are a lot >> of examples for that in Builtin.py already. > > I've finally got back to this and have the start of an implementation. I've > attached a diff, though I'm not sure what the preferred workflow is. Should > I push to github and / or create a bug in trac? It's best to create a pull request on github, potentially accompanied by a request for review on the developer mailing list. We get a notification about pull requests, but it's still better to give us an idea in what state you think your patch is and what kind of review you need. The review can then happen by commenting on the changes directly in github. > I'll probably add more > methods, but wanted to get feedback before doing so. Certainly the right decision. > I also intend to contribute other patches in the future. Please do. :) > One thing that I didn't expect is that I originally declared the method as > BuiltinMethod("startswith", "TT", "O", "_Pyx_StrStartsWith", > utility_code=str_startswith_utility_code), > and expected the specialization to only be used when both self and arg > where a str, but instead cython always used the specialization and added a > check for arg being a str before the specialization was called. I ended up > writing a function that works for both unicode & bytes self and an object arg. You don't really have to care about the type of the argument when applying this optimisation. As long as it's clear that the object that provides the method is a "str" (although it's potentially None even then!), it's clear what the method will do when being called, even if we don't know the argument type at compile time. Just provide a fallback, as you did anyway. I'll comment on your patch below. diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py +str_startswith_utility_code = UtilityCode( +proto=""" "proto" is for the forward declaration of the function signature. Except for very simple cases (short macros) the implementation goes into "impl". +static PyObject* _Pyx_StrStartsWith(PyObject* self, PyObject* arg) +{ + PyObject* ret; + + if ( PyBytes_CheckExact(self) && PyBytes_CheckExact(arg) ) { + if ( PyBytes_GET_SIZE(self) < PyBytes_GET_SIZE(arg) ) + ret = Py_False; + else if ( memcmp(PyBytes_AS_STRING(self), PyBytes_AS_STRING(arg), + PyBytes_GET_SIZE(arg)) == 0 ) + ret = Py_True; + else + ret = Py_False; + Py_INCREF(ret); + return ret; + } + + if ( PyUnicode_CheckExact(self) && PyUnicode_CheckExact(arg) ) { + if ( PyUnicode_GET_SIZE(self) < PyUnicode_GET_SIZE(arg) ) + ret = Py_False; + else if ( memcmp(PyUnicode_AS_UNICODE(self), PyUnicode_AS_UNICODE(arg), + PyUnicode_GET_DATA_SIZE(arg)) == 0 ) + ret = Py_True; + else + ret = Py_False; + Py_INCREF(ret); + return ret; + } + + return PyObject_CallMethod(self, "startswith", "O", arg); I'd split this up into two functions that can be applied to different types independently, and wrap it in a function that calls either one depending on PY_MAJOR_VERSION. After all, "str" is *known* to be "bytes" in Py2 and "unicode" in Py3. @@ -522,8 +557,12 @@ builtin_types_table = [ ]), ("bytes", "PyBytes_Type", []), - ("str", "PyString_Type", []), + ("str", "PyString_Type", [BuiltinMethod("startswith", "TO", "O", "_Pyx_StrStartsWith", + utility_code=str_startswith_utility_code), + ]), It's better to return a "bint" to avoid returning Python objects for True/False. The type character for that is "b". There's a "__Pyx_PyObject_IsTrue(obj)" macro that you can use to convert the fallback return value. It's usually also ok to copy error handling code from CPython, and to raise the exception directly without going into the fallback case. ("unicode", "PyUnicode_Type", [BuiltinMethod("join", "TO", "T", "PyUnicode_Join"), + BuiltinMethod("startswith", "TO", "O", "_Pyx_StrStartsWith", + utility_code=str_startswith_utility_code), ]), This is already optimised in Cython/Compiler/Optimize.py ("tailmatch"), basically because it allows different numbers of arguments that need to be dealt with. It may be worth going the same route for "str". The decision usually depends on how complex the code transformation is. The method table in Builtins is clearly limited. diff --git a/tests/run/stropts.pyx b/tests/run/stropts.pyx @@ -0,0 +1,84 @@ +cimport cython + + at cython.test_assert_path_exists( + '//AttributeNode[@member="_Pyx_StrStartsWith"]') +def str_startswith_str(): + """ + >>> str_startswith_str() + True + """ + + cdef str a + cdef str b + + a = '' + b = '' + return a.startswith(b) [...] I usually just implement one or a few test functions and use the doctest to pass in different values. Stefan From vitja.makarov at gmail.com Thu May 19 22:34:34 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Fri, 20 May 2011 00:34:34 +0400 Subject: [Cython] Scoped expressions and generators problem Message-ID: I don't know how to handle scopedexprs in generators, here are some examples: [(yield i) for i in l] or [i for i in yield] In Python3 language mode scoped expression is created for list comprehension and loop variable is moved there. So now it isn't stored inside generator closure and is lost between yields. Btw there is one more problem I hope that's easy to solve: yield expression inside scoped expression is counted twice. -- vitja. From jpe at wingware.com Thu May 19 22:42:47 2011 From: jpe at wingware.com (John Ehresman) Date: Thu, 19 May 2011 16:42:47 -0400 Subject: [Cython] Specializing str methods? In-Reply-To: <4DD570F5.9050306@behnel.de> References: <4DA4D997.7050709@wingware.com> <4DA51ECA.1090603@behnel.de> <4DA53920.8040000@behnel.de> <4DA5BCEA.8030501@wingware.com> <4DA5BFEA.8050001@behnel.de> <4DD542B4.1070802@wingware.com> <4DD570F5.9050306@behnel.de> Message-ID: <4DD580C7.7080102@wingware.com> On 5/19/11 3:35 PM, Stefan Behnel wrote: > This is already optimised in Cython/Compiler/Optimize.py ("tailmatch"), > basically because it allows different numbers of arguments that need to > be dealt with. It may be worth going the same route for "str". The > decision usually depends on how complex the code transformation is. The > method table in Builtins is clearly limited. I'll look at doing this in Optimize.py. The hunk of my patch below fixes a generic bug, though. Without it a utility function for a method is used, but the definition of it is never injected into the C file. Thanks, John diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 6ab8be0..ac7ca67 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -3746,6 +3746,8 @@ class AttributeNode(ExprNode): if entry.is_variable or entry.is_cmethod: self.type = entry.type self.member = entry.cname + if entry.utility_code: + env.use_utility_code(entry.utility_code) return else: # If it's not a variable or C method, it must be a Python From stefan_ml at behnel.de Fri May 20 10:27:02 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Fri, 20 May 2011 10:27:02 +0200 Subject: [Cython] Scoped expressions and generators problem In-Reply-To: References: Message-ID: <4DD625D6.4060404@behnel.de> Vitja Makarov, 19.05.2011 22:34: > I don't know how to handle scopedexprs in generators, here are some examples: > > [(yield i) for i in l] or [i for i in yield] > > In Python3 language mode scoped expression is created for list > comprehension and loop variable is moved there. Not only that. In Python 3 (and also for set/dict comprehensions in Py2.7), the above are basically generator expressions and the behaviour of yield inside of a generator expression is weird at best. >>> a = [(yield i) for i in (1,2,3)] >>> a at 0x1be2a00> >>> next(a) 1 >>> a.send(5) 2 >>> next(a) 3 >>> next(a) [5, None, None] The second case is simpler and more obvious as the yield expression only determines the iterable, which happens before entering the loop. Note, however, that the iterable is currently being evaluated inside of the wrong scope. http://trac.cython.org/cython_trac/ticket/600 > So now it isn't stored inside generator closure and is lost between yields. Right, it's a separate scope. I guess this means that expression scopes must behave differently when one of the surrounding scopes is a generator scope. They either have to somehow declare their local names in that outer scope, or the closure class generator would have to descend into these inner scopes as well to inject additional names into the closure, or we could let the yield expression node explicitly copy over local names from surrounding non-generator scopes into temps. The current workings of declaring a block local C variable would match best with the third way IMHO, even if that's not the cleanest solution. Otherwise, we'd also have to change the way scoped expressions work. > Btw there is one more problem I hope that's easy to solve: > yield expression inside scoped expression is counted twice. That means that the YieldNodeCollector must stop at scoped expression boundaries. However, as ticket #600 shows, this may not be completely trivial to fix. It might work to let the scoped expression nodes own the iterable node, and to use a CloneNode in the place where the iterable is used inside of the loop. That way, the scope node can directly decide which scope to evaluate the iterable node in. Stefan From stefan_ml at behnel.de Fri May 20 17:13:35 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Fri, 20 May 2011 17:13:35 +0200 Subject: [Cython] nonecheck directive Message-ID: <4DD6851F.4060709@behnel.de> Hi, why is the "nonecheck" directive set to False by default? Shouldn't it rather be a "I know what I'm doing" option that allows advanced users to trade speed for safety? The reason I'm asking is that I just enabled its evaluation in NoneCheckNode and immediately got crashes in the test suite. So its currently only half-heartedly safe because it's not being evaluated in a lot of places. That's a rather fragile situation, not only for refactorings. Stefan From robertwb at math.washington.edu Fri May 20 17:33:44 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Fri, 20 May 2011 08:33:44 -0700 Subject: [Cython] nonecheck directive In-Reply-To: <4DD6851F.4060709@behnel.de> References: <4DD6851F.4060709@behnel.de> Message-ID: On Fri, May 20, 2011 at 8:13 AM, Stefan Behnel wrote: > Hi, > > why is the "nonecheck" directive set to False by default? Shouldn't it > rather be a "I know what I'm doing" option that allows advanced users to > trade speed for safety? > > The reason I'm asking is that I just enabled its evaluation in NoneCheckNode > and immediately got crashes in the test suite. So its currently only > half-heartedly safe because it's not being evaluated in a lot of places. > That's a rather fragile situation, not only for refactorings. The reasoning was that we didn't want to have a major performance regression on existing code has already been written knowing these semantics, and also that we eventually plan to solve this more gracefully using control flow. - Robert From stefan_ml at behnel.de Sat May 21 07:57:20 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 21 May 2011 07:57:20 +0200 Subject: [Cython] nonecheck directive In-Reply-To: References: <4DD6851F.4060709@behnel.de> Message-ID: <4DD75440.20407@behnel.de> Robert Bradshaw, 20.05.2011 17:33: > On Fri, May 20, 2011 at 8:13 AM, Stefan Behnel wrote: >> why is the "nonecheck" directive set to False by default? Shouldn't it >> rather be a "I know what I'm doing" option that allows advanced users to >> trade speed for safety? Erm, trade safety for speed, obviously ... >> The reason I'm asking is that I just enabled its evaluation in NoneCheckNode >> and immediately got crashes in the test suite. So its currently only >> half-heartedly safe because it's not being evaluated in a lot of places. >> That's a rather fragile situation, not only for refactorings. > > The reasoning was that we didn't want to have a major performance > regression on existing code has already been written knowing these > semantics, and also that we eventually plan to solve this more > gracefully using control flow. I can see that there could have been a slight, potential performance regression due to additional None checks, even considering that the C compiler can often drop many of them due to its own control flow analysis, and even though the CPU's branch prediction can be expected to handle this quite well even in loops. However, for users, it's hard to predict where Cython can avoid None checks and where it cannot, so having to explicitly tell it to do None checks in a specific code section means that users encounter and analyse a crash first, potentially when switching to a newer Cython version. The opt-out way would have allowed them to disable it only for code sections where it is really getting in the way, and would have made it clear in their own code that something potentially unsafe is happening where they are on their own. I think that even in the face of future control flow analysis in Cython, it would still have been better to make it an opt-out rather than opt-in option, but I would expect that we can still switch the default setting when a suitable CFA step becomes available. In the future, I think we should be more careful with potentially harmful options, and always prefer safety over speed - *especially* when we know that the safe way will improve at some point. Stefan From d.s.seljebotn at astro.uio.no Sat May 21 09:07:13 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Sat, 21 May 2011 09:07:13 +0200 Subject: [Cython] nonecheck directive In-Reply-To: <4DD75440.20407@behnel.de> References: <4DD6851F.4060709@behnel.de> <4DD75440.20407@behnel.de> Message-ID: <4DD764A1.5090108@astro.uio.no> On 05/21/2011 07:57 AM, Stefan Behnel wrote: > Robert Bradshaw, 20.05.2011 17:33: >> On Fri, May 20, 2011 at 8:13 AM, Stefan Behnel wrote: >>> why is the "nonecheck" directive set to False by default? Shouldn't it >>> rather be a "I know what I'm doing" option that allows advanced users to >>> trade speed for safety? > > Erm, trade safety for speed, obviously ... > > >>> The reason I'm asking is that I just enabled its evaluation in >>> NoneCheckNode >>> and immediately got crashes in the test suite. So its currently only >>> half-heartedly safe because it's not being evaluated in a lot of places. >>> That's a rather fragile situation, not only for refactorings. >> >> The reasoning was that we didn't want to have a major performance >> regression on existing code has already been written knowing these >> semantics, and also that we eventually plan to solve this more >> gracefully using control flow. > > I can see that there could have been a slight, potential performance > regression due to additional None checks, even considering that the C > compiler can often drop many of them due to its own control flow > analysis, and even though the CPU's branch prediction can be expected to > handle this quite well even in loops. > > However, for users, it's hard to predict where Cython can avoid None > checks and where it cannot, so having to explicitly tell it to do None > checks in a specific code section means that users encounter and analyse > a crash first, potentially when switching to a newer Cython version. The > opt-out way would have allowed them to disable it only for code sections > where it is really getting in the way, and would have made it clear in > their own code that something potentially unsafe is happening where they > are on their own. > > I think that even in the face of future control flow analysis in Cython, > it would still have been better to make it an opt-out rather than opt-in > option, but I would expect that we can still switch the default setting > when a suitable CFA step becomes available. > > In the future, I think we should be more careful with potentially > harmful options, and always prefer safety over speed - *especially* when > we know that the safe way will improve at some point. There wasn't a point where anybody wasn't careful about this; it is simply something that was inherited from Pyrex. The nonecheck directive came much later. Dag Sverre From robertwb at math.washington.edu Sat May 21 09:39:43 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Sat, 21 May 2011 00:39:43 -0700 Subject: [Cython] nonecheck directive In-Reply-To: <4DD75440.20407@behnel.de> References: <4DD6851F.4060709@behnel.de> <4DD75440.20407@behnel.de> Message-ID: On Fri, May 20, 2011 at 10:57 PM, Stefan Behnel wrote: > Robert Bradshaw, 20.05.2011 17:33: >> >> On Fri, May 20, 2011 at 8:13 AM, Stefan Behnel wrote: >>> >>> why is the "nonecheck" directive set to False by default? Shouldn't it >>> rather be a "I know what I'm doing" option that allows advanced users to >>> trade speed for safety? > > Erm, trade safety for speed, obviously ... > > >>> The reason I'm asking is that I just enabled its evaluation in >>> NoneCheckNode >>> and immediately got crashes in the test suite. So its currently only >>> half-heartedly safe because it's not being evaluated in a lot of places. >>> That's a rather fragile situation, not only for refactorings. >> >> The reasoning was that we didn't want to have a major performance >> regression on existing code has already been written knowing these >> semantics, and also that we eventually plan to solve this more >> gracefully using control flow. > > I can see that there could have been a slight, potential performance > regression due to additional None checks, even considering that the C > compiler can often drop many of them due to its own control flow analysis, > and even though the CPU's branch prediction can be expected to handle this > quite well even in loops. It would be great if someone did some extensive benchmarking--maybe the overhead is negligible right now. > However, for users, it's hard to predict where Cython can avoid None checks > and where it cannot, so having to explicitly tell it to do None checks in a > specific code section means that users encounter and analyse a crash first, > potentially when switching to a newer Cython version. The opt-out way would > have allowed them to disable it only for code sections where it is really > getting in the way, and would have made it clear in their own code that > something potentially unsafe is happening where they are on their own. > > I think that even in the face of future control flow analysis in Cython, it > would still have been better to make it an opt-out rather than opt-in > option, but I would expect that we can still switch the default setting when > a suitable CFA step becomes available. > > In the future, I think we should be more careful with potentially harmful > options, and always prefer safety over speed - *especially* when we know > that the safe way will improve at some point. It's not as if we introduced a new feature, and then chose the unsafe version rather than the safe one. In this case (e.g. buffer indexing) we always default to the safe option. Rather, this is how the language has always been, and we introduced an option with overhead to make things safer but remaining 100% backwards compatible (in terms of performance and behavior) with existing code. - Robert From stefan_ml at behnel.de Sun May 22 07:14:49 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sun, 22 May 2011 07:14:49 +0200 Subject: [Cython] nonecheck directive In-Reply-To: <4DD764A1.5090108@astro.uio.no> References: <4DD6851F.4060709@behnel.de> <4DD75440.20407@behnel.de> <4DD764A1.5090108@astro.uio.no> Message-ID: <4DD89BC9.8020505@behnel.de> Dag Sverre Seljebotn, 21.05.2011 09:07: > On 05/21/2011 07:57 AM, Stefan Behnel wrote: >> In the future, I think we should be more careful with potentially >> harmful options, and always prefer safety over speed - *especially* when >> we know that the safe way will improve at some point. > > There wasn't a point where anybody wasn't careful about this; Sorry if I sounded offensive. It just felt too wrong from today's POV (which, I hope, is properly reflected by my paragraph above). > it is simply > something that was inherited from Pyrex. The nonecheck directive came much > later. Well, it wouldn't have been the first time we change the default behaviour from the way Pyrex originally worked to something we deem more correct. Looks like we missed that opportunity back then. I think Vitja's "uninitialised" branch is our way out of this. Stefan From vitja.makarov at gmail.com Sun May 22 09:10:04 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sun, 22 May 2011 11:10:04 +0400 Subject: [Cython] nonecheck directive In-Reply-To: <4DD89BC9.8020505@behnel.de> References: <4DD6851F.4060709@behnel.de> <4DD75440.20407@behnel.de> <4DD764A1.5090108@astro.uio.no> <4DD89BC9.8020505@behnel.de> Message-ID: 2011/5/22 Stefan Behnel : > Dag Sverre Seljebotn, 21.05.2011 09:07: >> >> On 05/21/2011 07:57 AM, Stefan Behnel wrote: >>> >>> In the future, I think we should be more careful with potentially >>> harmful options, and always prefer safety over speed - *especially* when >>> we know that the safe way will improve at some point. >> >> There wasn't a point where anybody wasn't careful about this; > > Sorry if I sounded offensive. It just felt too wrong from today's POV > (which, I hope, is properly reflected by my paragraph above). > > >> it is simply >> something that was inherited from Pyrex. The nonecheck directive came much >> later. > > Well, it wouldn't have been the first time we change the default behaviour > from the way Pyrex originally worked to something we deem more correct. > Looks like we missed that opportunity back then. > > I think Vitja's "uninitialised" branch is our way out of this. > Now it's called "_control_flow" btw. Now None initialization is removed and everything seems to work. -- vitja. From stefan_ml at behnel.de Sun May 22 14:33:22 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sun, 22 May 2011 14:33:22 +0200 Subject: [Cython] local variable handling in generators Message-ID: <4DD90292.8070505@behnel.de> Hi, I've been looking at the nqueens benchmark for a while, and I think it's actually not that a bad benchmark for generators. http://hg.python.org/benchmarks/file/tip/performance/bm_nqueens.py A better implementation only for Py2.7/Py3 is here: https://github.com/cython/cython/blob/master/Demos/benchmarks/nqueens.py Cython currently runs the first implementation about as fast as Py3.3: https://sage.math.washington.edu:8091/hudson/job/cython-devel-pybenchmarks-py3k/lastSuccessfulBuild/artifact/chart.html and the second one more than 3x as fast: https://sage.math.washington.edu:8091/hudson/view/bench/job/cython-devel-cybenchmarks-py3k/lastSuccessfulBuild/artifact/chart.html However, I think there's still some space for improvements, and local variables are part of that. For generator functions that do non-trivial things between yields, I think that local variables will quickly become a bottleneck. Currently, they are always closure fields, so any access to them will use a pointer indirection to a foreign struct, originally passed in as an argument to the function. Given that generators often do Python object manipulation through C-API calls, any such call will basically require the C compiler to assume that all values in the closure may have changed, thus disabling any optimisations for them. The same applies to many other object related operations or pointer operations (even DECREF!), as the C compiler cannot know that the generator function owns the closure during its lifetime exclusively. I think it would be worth changing the current implementation to use local C variables for local Cython variables in the generator, and to copy the values back into/from the closure around yields. I'd even let local Python references start off as NULL when the generator is created, given that Vitek's branch can eliminate None initialisations now. I started looking into this a bit, but it's not a quick change. The main problem I see is the current code duplication between the generator body node and the DefNode. It would be better if both could share more code. Basically, if local variables become truly local, the only differences will be that they come from call arguments in one case and from the closure in the other, and that generators have the additional jump-to-yield entry step. Everything else could hopefully be identical. Once again, this goes hand in hand with the still pending DefNode refactoring... Stefan From d.s.seljebotn at astro.uio.no Sun May 22 21:48:57 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Sun, 22 May 2011 21:48:57 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: <4DD90292.8070505@behnel.de> References: <4DD90292.8070505@behnel.de> Message-ID: <4DD968A9.5070605@astro.uio.no> On 05/22/2011 02:33 PM, Stefan Behnel wrote: > Hi, > > I've been looking at the nqueens benchmark for a while, and I think it's > actually not that a bad benchmark for generators. > > http://hg.python.org/benchmarks/file/tip/performance/bm_nqueens.py > > A better implementation only for Py2.7/Py3 is here: > > https://github.com/cython/cython/blob/master/Demos/benchmarks/nqueens.py > > Cython currently runs the first implementation about as fast as Py3.3: > > https://sage.math.washington.edu:8091/hudson/job/cython-devel-pybenchmarks-py3k/lastSuccessfulBuild/artifact/chart.html > > > and the second one more than 3x as fast: > > https://sage.math.washington.edu:8091/hudson/view/bench/job/cython-devel-cybenchmarks-py3k/lastSuccessfulBuild/artifact/chart.html > > > However, I think there's still some space for improvements, and local > variables are part of that. For generator functions that do non-trivial > things between yields, I think that local variables will quickly become > a bottleneck. Currently, they are always closure fields, so any access > to them will use a pointer indirection to a foreign struct, originally > passed in as an argument to the function. Given that generators often do > Python object manipulation through C-API calls, any such call will > basically require the C compiler to assume that all values in the > closure may have changed, thus disabling any optimisations for them. The > same applies to many other object related operations or pointer > operations (even DECREF!), as the C compiler cannot know that the > generator function owns the closure during its lifetime exclusively. > > I think it would be worth changing the current implementation to use > local C variables for local Cython variables in the generator, and to > copy the values back into/from the closure around yields. I'd even let > local Python references start off as NULL when the generator is created, > given that Vitek's branch can eliminate None initialisations now. Keep in mind that if speed is the objective, another idea is to use real C coroutines. This would likely be faster than anything we can make up ourselves; a single stack jump is bound to be faster than copying things in and out of the stack. Of course, probably more work. And then portability as the API is seperate for Windows (fibers) and POSIX (makecontext). But I don't think there's a lack of compatability layer libraries which unite the platform-specific APIs. Dag Sverre From stefan_ml at behnel.de Mon May 23 08:40:16 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 08:40:16 +0200 Subject: [Cython] C stack based coroutines (was: local variable handling in generators) In-Reply-To: <4DD968A9.5070605@astro.uio.no> References: <4DD90292.8070505@behnel.de> <4DD968A9.5070605@astro.uio.no> Message-ID: <4DDA0150.1020009@behnel.de> Dag Sverre Seljebotn, 22.05.2011 21:48: > Keep in mind that if speed is the objective, another idea is to use real C > coroutines. This would likely be faster than anything we can make up > ourselves; a single stack jump is bound to be faster than copying things in > and out of the stack. > > Of course, probably more work. And then portability as the API is seperate > for Windows (fibers) and POSIX (makecontext). But I don't think there's a > lack of compatability layer libraries which unite the platform-specific APIs. What if we have to call back into CPython? Would that work if the call ends up on a different stack than previous ones? What about CPython thread switches and signal handlers? Wikipedia has a couple of things to say about coroutines in C: http://en.wikipedia.org/wiki/Coroutine#Implementations_for_C including links to some libraries that are supposed to be portable: http://xmailserver.org/libpcl.html http://software.schmorp.de/pkg/libcoro.html http://code.google.com/p/libconcurrency/ http://www.dekorte.com/projects/opensource/libCoroutine/ http://www.goron.de/~froese/coro/ Overall, I think this has some potential but also major uncertainties. And it's a substantially larger change than making local variables C variables. May have made a good GSoC topic... Stefan From vitja.makarov at gmail.com Mon May 23 10:13:38 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 23 May 2011 12:13:38 +0400 Subject: [Cython] local variable handling in generators In-Reply-To: <4DD90292.8070505@behnel.de> References: <4DD90292.8070505@behnel.de> Message-ID: 2011/5/22 Stefan Behnel : > Hi, > > I've been looking at the nqueens benchmark for a while, and I think it's > actually not that a bad benchmark for generators. > > http://hg.python.org/benchmarks/file/tip/performance/bm_nqueens.py > > A better implementation only for Py2.7/Py3 is here: > > https://github.com/cython/cython/blob/master/Demos/benchmarks/nqueens.py > > Cython currently runs the first implementation about as fast as Py3.3: > > https://sage.math.washington.edu:8091/hudson/job/cython-devel-pybenchmarks-py3k/lastSuccessfulBuild/artifact/chart.html > > and the second one more than 3x as fast: > > https://sage.math.washington.edu:8091/hudson/view/bench/job/cython-devel-cybenchmarks-py3k/lastSuccessfulBuild/artifact/chart.html > > However, I think there's still some space for improvements, and local > variables are part of that. For generator functions that do non-trivial > things between yields, I think that local variables will quickly become a > bottleneck. Currently, they are always closure fields, so any access to them > will use a pointer indirection to a foreign struct, originally passed in as > an argument to the function. Given that generators often do Python object > manipulation through C-API calls, any such call will basically require the C > compiler to assume that all values in the closure may have changed, thus > disabling any optimisations for them. The same applies to many other object > related operations or pointer operations (even DECREF!), as the C compiler > cannot know that the generator function owns the closure during its lifetime > exclusively. > > I think it would be worth changing the current implementation to use local C > variables for local Cython variables in the generator, and to copy the > values back into/from the closure around yields. I'd even let local Python > references start off as NULL when the generator is created, given that > Vitek's branch can eliminate None initialisations now. > > I started looking into this a bit, but it's not a quick change. The main > problem I see is the current code duplication between the generator body > node and the DefNode. It would be better if both could share more code. > Basically, if local variables become truly local, the only differences will > be that they come from call arguments in one case and from the closure in > the other, and that generators have the additional jump-to-yield entry step. > Everything else could hopefully be identical. > > Once again, this goes hand in hand with the still pending DefNode > refactoring... > With live variable analysis that should be easy to save/restore only active variables at the yield point. Btw now only reaching definitions analysis is implemented. I'm going to optimize by replacing sets with bitsets. And then try to implement live varaiables. I'm going to delete variable reference using active variable info, but that could introduce small incompatiblity with CPython: a = X print a # <- a will be decrefed here print 'the end' -- vitja. From stefan_ml at behnel.de Mon May 23 10:29:10 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 10:29:10 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> Message-ID: <4DDA1AD6.1070309@behnel.de> Vitja Makarov, 23.05.2011 10:13: > With live variable analysis that should be easy to save/restore only > active variables at the yield point. "Active" in the sense of "modified", I suppose? That's what I was expecting. > Btw now only reaching definitions analysis is implemented. I'm going > to optimize by replacing sets with bitsets. And then try to implement > live varaiables. > > I'm going to delete variable reference using active variable info, but > that could introduce small incompatiblity with CPython: > a = X > print a #<- a will be decrefed here > print 'the end' That incompatibility is not small at all. It breaks this code: x = b'abc' cdef char* c = x Even if 'x' is no longer used after this point, it *must not* get freed before 'c' is going away as well. That's basically impossible to decide, as users may pass 'c' into a function that stores it away for alter use. I'm fine with deallocating variables that are no longer used after the user explicitly assigned None to them (i.e. replace the None assignment by a simple "DECREF + set to NULL" in that case). I don't think we should be doing more than that. Stefan From vitja.makarov at gmail.com Mon May 23 10:50:35 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 23 May 2011 12:50:35 +0400 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDA1AD6.1070309@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> Message-ID: 2011/5/23 Stefan Behnel : > Vitja Makarov, 23.05.2011 10:13: >> >> With live variable analysis that should be easy to save/restore only >> active variables at the yield point. > > "Active" in the sense of "modified", I suppose? That's what I was expecting. > Active means that variable value will be used. In my example after 'print a' a isn't used anymore. > >> Btw now only reaching definitions analysis is implemented. I'm going >> to optimize by replacing sets with bitsets. And then try to implement >> live varaiables. >> >> I'm going to delete variable reference using active variable info, but >> that could introduce small incompatiblity with CPython: >> a = X >> print a #<- a will be decrefed here >> print 'the end' > > That incompatibility is not small at all. It breaks this code: > > ? ?x = b'abc' > ? ?cdef char* c = x > > Even if 'x' is no longer used after this point, it *must not* get freed > before 'c' is going away as well. That's basically impossible to decide, as > users may pass 'c' into a function that stores it away for alter use. > Yeah. That's hard to detect. But x could be marked as "don't decref when not-active" > I'm fine with deallocating variables that are no longer used after the user > explicitly assigned None to them (i.e. replace the None assignment by a > simple "DECREF + set to NULL" in that case). I don't think we should be > doing more than that. > Hmm. Why should that be NULL if user sets it to None? For instance: for i in args: print i this code will be translated into: PyObject *i = NULL; for (;;) { tmp = next(); if (!tmp) break; Pyx_XDECREF(i); i = tmp; print(i); } using active variables information this could be translated into: PyObject *i = NULL; for (;;) { tmp = next(); if (!tmp) break; i = tmp; print(i); Pyx_DECREF(i); } -- vitja. From d.s.seljebotn at astro.uio.no Mon May 23 11:04:52 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Mon, 23 May 2011 11:04:52 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> Message-ID: <4DDA2334.3070106@astro.uio.no> On 05/23/2011 10:50 AM, Vitja Makarov wrote: > 2011/5/23 Stefan Behnel: >> Vitja Makarov, 23.05.2011 10:13: >>> >>> With live variable analysis that should be easy to save/restore only >>> active variables at the yield point. >> >> "Active" in the sense of "modified", I suppose? That's what I was expecting. >> > > Active means that variable value will be used. In my example after > 'print a' a isn't used anymore. > >> >>> Btw now only reaching definitions analysis is implemented. I'm going >>> to optimize by replacing sets with bitsets. And then try to implement >>> live varaiables. >>> >>> I'm going to delete variable reference using active variable info, but >>> that could introduce small incompatiblity with CPython: >>> a = X >>> print a #<- a will be decrefed here >>> print 'the end' >> >> That incompatibility is not small at all. It breaks this code: >> >> x = b'abc' >> cdef char* c = x >> >> Even if 'x' is no longer used after this point, it *must not* get freed >> before 'c' is going away as well. That's basically impossible to decide, as >> users may pass 'c' into a function that stores it away for alter use. >> > > Yeah. That's hard to detect. But x could be marked as "don't decref > when not-active" def f(object o): cdef char* buf buf = get_buffer_of_obj(o) call_c_func(buf) So there's a lot of variables that would have to be marked this way (but not all, I can see that). Dag Sverre From stefan_ml at behnel.de Mon May 23 11:15:07 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 11:15:07 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> Message-ID: <4DDA259B.1000203@behnel.de> Vitja Makarov, 23.05.2011 10:50: > 2011/5/23 Stefan Behnel: >> Vitja Makarov, 23.05.2011 10:13: >>> >>> With live variable analysis that should be easy to save/restore only >>> active variables at the yield point. >> >> "Active" in the sense of "modified", I suppose? That's what I was expecting. > > Active means that variable value will be used. In my example after > 'print a' a isn't used anymore. That's not correct then. In a generator, a modified value must be kept alive over a yield, even if it is no longer used afterwards. We can safely reduce the write-back code to modified values, but we cannot reduce it to values to that will be used later on. >>> Btw now only reaching definitions analysis is implemented. I'm going >>> to optimize by replacing sets with bitsets. And then try to implement >>> live varaiables. >>> >>> I'm going to delete variable reference using active variable info, but >>> that could introduce small incompatiblity with CPython: >>> a = X >>> print a #<- a will be decrefed here >>> print 'the end' >> >> That incompatibility is not small at all. It breaks this code: >> >> x = b'abc' >> cdef char* c = x >> >> Even if 'x' is no longer used after this point, it *must not* get freed >> before 'c' is going away as well. That's basically impossible to decide, as >> users may pass 'c' into a function that stores it away for alter use. > > Yeah. That's hard to detect. But x could be marked as "don't decref > when not-active" How would you know that it needs to be marked like that? You won't necessarily see it in the code that a pointer was taken from the value, that might have happened within a called function. >> I'm fine with deallocating variables that are no longer used after the user >> explicitly assigned None to them (i.e. replace the None assignment by a >> simple "DECREF + set to NULL" in that case). I don't think we should be >> doing more than that. > > Hmm. Why should that be NULL if user sets it to None? Because there is no user visible difference. None will always be available, even if the Cython code no longer holds a reference to it. So changing "x = None" into "Py_DECREF(x); x=NULL" is just fine, as long as we can make sure 'x' is never accessed after this point. > For instance: > > for i in args: > print i > > this code will be translated into: > > PyObject *i = NULL; > > for (;;) > { > tmp = next(); > if (!tmp) break; > > Pyx_XDECREF(i); > i = tmp; > print(i); > } > > using active variables information this could be translated into: > > PyObject *i = NULL; > > for (;;) > { > tmp = next(); > if (!tmp) break; > > i = tmp; > print(i); > Pyx_DECREF(i); > } That's not correct, though. Python semantics dictate that 'i' must keep its value until the end of the function or until it's being reassigned to, whatever comes first. Remember that objects can have deallocators in Python. That must not be called at an undefined point. The only thing that can safely be special cased is None. It's common in Python code to set a variable to None when the value is worth being deallocated (e.g. a large data structure). Cython can optimise this as I indicated above. Stefan From vitja.makarov at gmail.com Mon May 23 11:24:07 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 23 May 2011 13:24:07 +0400 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDA259B.1000203@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> Message-ID: 2011/5/23 Stefan Behnel : > Vitja Makarov, 23.05.2011 10:50: >> >> 2011/5/23 Stefan Behnel: >>> >>> Vitja Makarov, 23.05.2011 10:13: >>>> >>>> With live variable analysis that should be easy to save/restore only >>>> active variables at the yield point. >>> >>> "Active" in the sense of "modified", I suppose? That's what I was >>> expecting. >> >> Active means that variable value will be used. In my example after >> 'print a' a isn't used anymore. > > That's not correct then. In a generator, a modified value must be kept alive > over a yield, even if it is no longer used afterwards. > > We can safely reduce the write-back code to modified values, but we cannot > reduce it to values to that will be used later on. > I'm not sure how to get modified variables list at yield point. Now I only know which assignments reach yield point. > >>>> Btw now only reaching definitions analysis is implemented. I'm going >>>> to optimize by replacing sets with bitsets. And then try to implement >>>> live varaiables. >>>> >>>> I'm going to delete variable reference using active variable info, but >>>> that could introduce small incompatiblity with CPython: >>>> a = X >>>> print a #<- a will be decrefed here >>>> print 'the end' >>> >>> That incompatibility is not small at all. It breaks this code: >>> >>> ? ?x = b'abc' >>> ? ?cdef char* c = x >>> >>> Even if 'x' is no longer used after this point, it *must not* get freed >>> before 'c' is going away as well. That's basically impossible to decide, >>> as >>> users may pass 'c' into a function that stores it away for alter use. >> >> Yeah. That's hard to detect. But x could be marked as "don't decref >> when not-active" > > How would you know that it needs to be marked like that? You won't > necessarily see it in the code that a pointer was taken from the value, that > might have happened within a called function. > > >>> I'm fine with deallocating variables that are no longer used after the >>> user >>> explicitly assigned None to them (i.e. replace the None assignment by a >>> simple "DECREF + set to NULL" in that case). I don't think we should be >>> doing more than that. >> >> Hmm. Why should that be NULL if user sets it to None? > > Because there is no user visible difference. None will always be available, > even if the Cython code no longer holds a reference to it. So changing "x = > None" into "Py_DECREF(x); x=NULL" is just fine, as long as we can make sure > 'x' is never accessed after this point. > > >> For instance: >> >> for i in args: >> ? ? print i >> >> this code will be translated into: >> >> PyObject *i = NULL; >> >> for (;;) >> { >> ? ?tmp = next(); >> ? ?if (!tmp) break; >> >> ? Pyx_XDECREF(i); >> ? i = tmp; >> ? print(i); >> } >> >> using active variables information this could be translated into: >> >> PyObject *i = NULL; >> >> for (;;) >> { >> ? ?tmp = next(); >> ? ?if (!tmp) break; >> >> ? i = tmp; >> ? print(i); >> ? Pyx_DECREF(i); >> } > > That's not correct, though. Python semantics dictate that 'i' must keep its > value until the end of the function or until it's being reassigned to, > whatever comes first. Remember that objects can have deallocators in Python. > That must not be called at an undefined point. > > The only thing that can safely be special cased is None. It's common in > Python code to set a variable to None when the value is worth being > deallocated (e.g. a large data structure). Cython can optimise this as I > indicated above. > Ohh, I see that variable references couldn't be simply removed. Unused result reference removal seems safe to me: a = foo() # a will be assigned to NULL here print -- vitja. From stefan_ml at behnel.de Mon May 23 11:29:45 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 11:29:45 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDA259B.1000203@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> Message-ID: <4DDA2909.20604@behnel.de> Stefan Behnel, 23.05.2011 11:15: > Vitja Makarov, 23.05.2011 10:50: >> 2011/5/23 Stefan Behnel: >>> I'm fine with deallocating variables that are no longer used after the user >>> explicitly assigned None to them (i.e. replace the None assignment by a >>> simple "DECREF + set to NULL" in that case). I don't think we should be >>> doing more than that. >> >> Hmm. Why should that be NULL if user sets it to None? > > Because there is no user visible difference. None will always be available, > even if the Cython code no longer holds a reference to it. So changing "x = > None" into "Py_DECREF(x); x=NULL" is just fine, as long as we can make sure > 'x' is never accessed after this point. The difference is clearer when I spell out the code for the first example, too: # x = None Py_INCREF(None) Py_DECREF(x) x = None would be optimised into # x = None Py_DECREF(x) x = NULL That's likely not a big difference, assuming that setting 'x' to None was worth it for the user, i.e. it will clean up the referenced object at that point. It may still be worth it inside of generators and on function return, which may now have one variable less to clean up or store away. A None value would still have to be DECREF-ed at least. Stefan From stefan_ml at behnel.de Mon May 23 11:34:07 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 11:34:07 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> Message-ID: <4DDA2A0F.4050303@behnel.de> Vitja Makarov, 23.05.2011 11:24: > 2011/5/23 Stefan Behnel: >> Vitja Makarov, 23.05.2011 10:50: >>> >>> 2011/5/23 Stefan Behnel: >>>> >>>> Vitja Makarov, 23.05.2011 10:13: >>>>> >>>>> With live variable analysis that should be easy to save/restore only >>>>> active variables at the yield point. >>>> >>>> "Active" in the sense of "modified", I suppose? That's what I was >>>> expecting. >>> >>> Active means that variable value will be used. In my example after >>> 'print a' a isn't used anymore. >> >> That's not correct then. In a generator, a modified value must be kept alive >> over a yield, even if it is no longer used afterwards. >> >> We can safely reduce the write-back code to modified values, but we cannot >> reduce it to values to that will be used later on. > > I'm not sure how to get modified variables list at yield point. Now I > only know which assignments reach yield point. But then you already know which variables were assigned to, right? That's all you need. >>> For instance: >>> >>> for i in args: >>> print i >>> >>> this code will be translated into: >>> >>> PyObject *i = NULL; >>> >>> for (;;) >>> { >>> tmp = next(); >>> if (!tmp) break; >>> >>> Pyx_XDECREF(i); >>> i = tmp; >>> print(i); >>> } >>> >>> using active variables information this could be translated into: >>> >>> PyObject *i = NULL; >>> >>> for (;;) >>> { >>> tmp = next(); >>> if (!tmp) break; >>> >>> i = tmp; >>> print(i); >>> Pyx_DECREF(i); >>> } >> >> That's not correct, though. Python semantics dictate that 'i' must keep its >> value until the end of the function or until it's being reassigned to, >> whatever comes first. Remember that objects can have deallocators in Python. >> That must not be called at an undefined point. >> >> The only thing that can safely be special cased is None. It's common in >> Python code to set a variable to None when the value is worth being >> deallocated (e.g. a large data structure). Cython can optimise this as I >> indicated above. > > Ohh, I see that variable references couldn't be simply removed. > > Unused result reference removal seems safe to me: > > a = foo() # a will be assigned to NULL here > print No, same thing: the reference that 'a' holds here may be important, so we cannot just drop it at an arbitrary point. There's (likely) a reason the user chose to use a variable, instead of just letting the return value fall off the shelve silently. Stefan From stefan_ml at behnel.de Mon May 23 11:57:20 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 11:57:20 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDA2909.20604@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> Message-ID: <4DDA2F80.3060907@behnel.de> Stefan Behnel, 23.05.2011 11:29: > Stefan Behnel, 23.05.2011 11:15: >> Vitja Makarov, 23.05.2011 10:50: >>> 2011/5/23 Stefan Behnel: >>>> I'm fine with deallocating variables that are no longer used after the >>>> user >>>> explicitly assigned None to them (i.e. replace the None assignment by a >>>> simple "DECREF + set to NULL" in that case). I don't think we should be >>>> doing more than that. >>> >>> Hmm. Why should that be NULL if user sets it to None? >> >> Because there is no user visible difference. None will always be available, >> even if the Cython code no longer holds a reference to it. So changing "x = >> None" into "Py_DECREF(x); x=NULL" is just fine, as long as we can make sure >> 'x' is never accessed after this point. > > The difference is clearer when I spell out the code for the first example, > too: > > # x = None > Py_INCREF(None) > Py_DECREF(x) > x = None > > would be optimised into > > # x = None > Py_DECREF(x) > x = NULL > > That's likely not a big difference, assuming that setting 'x' to None was > worth it for the user, i.e. it will clean up the referenced object at that > point. It may still be worth it inside of generators and on function > return, which may now have one variable less to clean up or store away. A > None value would still have to be DECREF-ed at least. Then again, "del x" would be a more obvious way to spell this ... Stefan From robertwb at math.washington.edu Mon May 23 20:09:50 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Mon, 23 May 2011 11:09:50 -0700 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDA2F80.3060907@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> Message-ID: On Mon, May 23, 2011 at 2:57 AM, Stefan Behnel wrote: > Stefan Behnel, 23.05.2011 11:29: >> >> Stefan Behnel, 23.05.2011 11:15: >>> >>> Vitja Makarov, 23.05.2011 10:50: >>>> >>>> 2011/5/23 Stefan Behnel: >>>>> >>>>> I'm fine with deallocating variables that are no longer used after the >>>>> user >>>>> explicitly assigned None to them (i.e. replace the None assignment by a >>>>> simple "DECREF + set to NULL" in that case). I don't think we should be >>>>> doing more than that. >>>> >>>> Hmm. Why should that be NULL if user sets it to None? >>> >>> Because there is no user visible difference. None will always be >>> available, >>> even if the Cython code no longer holds a reference to it. So changing "x >>> = >>> None" into "Py_DECREF(x); x=NULL" is just fine, as long as we can make >>> sure >>> 'x' is never accessed after this point. >> >> The difference is clearer when I spell out the code for the first example, >> too: >> >> # x = None >> Py_INCREF(None) >> Py_DECREF(x) >> x = None >> >> would be optimised into >> >> # x = None >> Py_DECREF(x) >> x = NULL >> >> That's likely not a big difference, assuming that setting 'x' to None was >> worth it for the user, i.e. it will clean up the referenced object at that >> point. It may still be worth it inside of generators and on function >> return, which may now have one variable less to clean up or store away. A >> None value would still have to be DECREF-ed at least. > > Then again, "del x" would be a more obvious way to spell this ... And then setting it to NULL would actually be correct. In any case, I'm -1 to deleting references once their no longer used, we must wait 'till the end of the function, and I'm not sure the savings would be that great either. In terms of packing/unpacking the variables onto the local C stack, until we have live variable analysis (and even then) it may still be more expensive in some cases than just leaving it there, right? - Robert From romain.py at gmail.com Mon May 23 20:33:34 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Mon, 23 May 2011 19:33:34 +0100 Subject: [Cython] Scope resolution in a Visitor Message-ID: <20110523183333.GA5154@ubuntu> Hi I'm doing the PyPy backend for Cython Summer of Code project and I would like to know if there is a way of getting the AST Node responsible for the declaration of a variable. For example : def func(): def func(): pass func() In the situation where I'm currently traversing the function call, I would like to get the function declaration node. Is there already something to do that ? Cheers Romain From stefan_ml at behnel.de Mon May 23 20:39:27 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 23 May 2011 20:39:27 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> Message-ID: <4DDAA9DF.2000809@behnel.de> Robert Bradshaw, 23.05.2011 20:09: > In any case, I'm -1 to deleting references once their no longer used, > we must wait 'till the end of the function, and I'm not sure the > savings would be that great either. Agreed. > In terms of packing/unpacking the variables onto the local C stack, > until we have live variable analysis (and even then) it may still be > more expensive in some cases than just leaving it there, right? I agree that it can be substantially more expensive to write back *all* variables on each yield, although it doesn't have to be. It largely depends on the generator code. However, once we really know which values change between yield calls, i.e. which ones need to be stored away, it will actually be less expensive in most cases. We currently pay the indirection penalty for each access, even read access, whereas the C compiler can then keep important variables in registers and only write them back once per yield. Stefan From vitja.makarov at gmail.com Mon May 23 21:29:21 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 23 May 2011 23:29:21 +0400 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> Message-ID: 2011/5/23 Robert Bradshaw : >> >> Then again, "del x" would be a more obvious way to spell this ... > > And then setting it to NULL would actually be correct. > That is already done ;) But usually you wouldn't use del statement in your code. > In any case, I'm -1 to deleting references once their no longer used, > we must wait 'till the end of the function, and I'm not sure the > savings would be that great either. > Ok. Example with char * makes me think that this is not a good idea. > In terms of packing/unpacking the variables onto the local C stack, > until we have live variable analysis (and even then) it may still be > more expensive in some cases than just leaving it there, right? > We can try, that isn't hard to implement and compare. -- vitja. From vitja.makarov at gmail.com Mon May 23 21:33:36 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 23 May 2011 23:33:36 +0400 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDAA9DF.2000809@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> <4DDAA9DF.2000809@behnel.de> Message-ID: 2011/5/23 Stefan Behnel : > > However, once we really know which values change between yield calls, i.e. > which ones need to be stored away, it will actually be less expensive in > most cases. We currently pay the indirection penalty for each access, even > read access, whereas the C compiler can then keep important variables in > registers and only write them back once per yield. > I think that all not NULL variables should be saved/restored inside yield. I can not really track changes only assignments. for i in a: yield i # j is NULL here for j in b: yield j # a, b, i ,j should be saved/restored -- vitja. From stefan_ml at behnel.de Tue May 24 06:33:36 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 24 May 2011 06:33:36 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> <4DDAA9DF.2000809@behnel.de> Message-ID: <4DDB3520.5020609@behnel.de> Vitja Makarov, 23.05.2011 21:33: > 2011/5/23 Stefan Behnel: >> >> However, once we really know which values change between yield calls, i.e. >> which ones need to be stored away, it will actually be less expensive in >> most cases. We currently pay the indirection penalty for each access, even >> read access, whereas the C compiler can then keep important variables in >> registers and only write them back once per yield. >> > > I think that all not NULL variables should be saved/restored inside yield. > I can not really track changes only assignments. I mean "assignments" when I write "changes". When a variable is being assigned to, we should assume that its value changed. Users can be expected to be smart enough to avoid unnecessary assignments in most cases, there's no need to put work into optimising them away automatically. > for i in a: > yield i # j is NULL here > for j in b: > yield j # a, b, i ,j should be saved/restored Right. However, in general, we can expect that most variables will have been initialised on a yield. We can still avoid storing away C typed variables that are not being used later on, because they are not reference counted. And if the user sets 'a' and 'i' to None between the loops, they won't need to be saved on the second yield either. But that's an optimisation, not a requirement. Stefan From stefan_ml at behnel.de Tue May 24 06:56:19 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 24 May 2011 06:56:19 +0200 Subject: [Cython] Scope resolution in a Visitor In-Reply-To: <20110523183333.GA5154@ubuntu> References: <20110523183333.GA5154@ubuntu> Message-ID: <4DDB3A73.4080808@behnel.de> Romain Guillebert, 23.05.2011 20:33: > I'm doing the PyPy backend for Cython Summer of Code project and I would > like to know if there is a way of getting the AST Node responsible for > the declaration of a variable. > > For example : > > def func(): > def func(): > pass > > func() > > In the situation where I'm currently traversing the function call, I > would like to get the function declaration node. > Is there already something to do that ? What for? What kind of information do you need from it? In Cython, the metadata about a name is stored in its symbol table entry. The call to "func" is a SimpleCallNode that holds a NameNode which has an "entry" attribute. The entry knows the name, type, signature, etc. of the function that is being called. Note, however, that you need to run both the "analyse declarations" step and the "analyse types/expression" step to figure out all information about the name. The declaration analysis will add the definition of "func" to the symbol table, so you can look it up ("env.lookup('func')") from that point on. Does that help? Stefan From romain.py at gmail.com Tue May 24 19:22:39 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Tue, 24 May 2011 18:22:39 +0100 Subject: [Cython] Scope resolution in a Visitor In-Reply-To: <4DDB3A73.4080808@behnel.de> References: <20110523183333.GA5154@ubuntu> <4DDB3A73.4080808@behnel.de> Message-ID: <20110524172239.GA12632@ubuntu> On Tue, May 24, 2011 at 06:56:19AM +0200, Stefan Behnel wrote: > Romain Guillebert, 23.05.2011 20:33: > >I'm doing the PyPy backend for Cython Summer of Code project and I would > >like to know if there is a way of getting the AST Node responsible for > >the declaration of a variable. > > > >For example : > > > >def func(): > > def func(): > > pass > > > > func() > > > >In the situation where I'm currently traversing the function call, I > >would like to get the function declaration node. > >Is there already something to do that ? > > What for? What kind of information do you need from it? > > In Cython, the metadata about a name is stored in its symbol table > entry. The call to "func" is a SimpleCallNode that holds a NameNode > which has an "entry" attribute. The entry knows the name, type, > signature, etc. of the function that is being called. > > Note, however, that you need to run both the "analyse declarations" > step and the "analyse types/expression" step to figure out all > information about the name. The declaration analysis will add the > definition of "func" to the symbol table, so you can look it up > ("env.lookup('func')") from that point on. > > Does that help? > > Stefan I want to generate standard python function from "cdef extern from" function, but I need to annotate these function as they may require a special treatment (for passing value by reference), also, I may turn C macros into a call to a C function returning the macro itself. cdef extern from "stdio.h": cdef int BUFSIZ Will be turned into : def get_BUFSIZ(): # whatever So I need to turn every access to BUFSIZ into a function call. Cheers Romain From vitja.makarov at gmail.com Tue May 24 21:33:02 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Tue, 24 May 2011 23:33:02 +0400 Subject: [Cython] CF and finally clause Message-ID: Hi! When I create control flow graph I have to visit finally clause twice. This is required because of different outputs should be generated for success and exception case: try: a = might_raise() finally: pass # 'a' might be uninitialized here print(a) # and definitely defined here So after tracking both cases I have to merge states back because same code is generated for each. Maybe it's a good idea to split success/exception case by copying it at PostParse transform? -- vitja. From robertwb at math.washington.edu Tue May 24 22:07:02 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 24 May 2011 13:07:02 -0700 Subject: [Cython] CF and finally clause In-Reply-To: References: Message-ID: On Tue, May 24, 2011 at 12:33 PM, Vitja Makarov wrote: > Hi! > > When I create control flow graph I have to visit finally clause twice. > This is required because of different outputs should be generated for > success and exception case: > > try: > ? ?a = might_raise() > finally: > ? ?pass # 'a' might be uninitialized here > print(a) ?# and definitely defined here > > So after tracking both cases I have to merge states back because same > code is generated for each. > > Maybe it's a good idea to split success/exception case by copying it > at PostParse transform? -1 I don't see any difference compared to merging the states from if b: a = None else: # don't assign to a - Robert From stefan_ml at behnel.de Tue May 24 22:07:22 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 24 May 2011 22:07:22 +0200 Subject: [Cython] Scope resolution in a Visitor In-Reply-To: <20110524172239.GA12632@ubuntu> References: <20110523183333.GA5154@ubuntu> <4DDB3A73.4080808@behnel.de> <20110524172239.GA12632@ubuntu> Message-ID: <4DDC0FFA.206@behnel.de> Romain Guillebert, 24.05.2011 19:22: > On Tue, May 24, 2011 at 06:56:19AM +0200, Stefan Behnel wrote: >> Romain Guillebert, 23.05.2011 20:33: >>> I'm doing the PyPy backend for Cython Summer of Code project and I would >>> like to know if there is a way of getting the AST Node responsible for >>> the declaration of a variable. >>> >>> For example : >>> >>> def func(): >>> def func(): >>> pass >>> >>> func() >>> >>> In the situation where I'm currently traversing the function call, I >>> would like to get the function declaration node. >>> Is there already something to do that ? >> >> What for? What kind of information do you need from it? >> >> In Cython, the metadata about a name is stored in its symbol table >> entry. The call to "func" is a SimpleCallNode that holds a NameNode >> which has an "entry" attribute. The entry knows the name, type, >> signature, etc. of the function that is being called. >> >> Note, however, that you need to run both the "analyse declarations" >> step and the "analyse types/expression" step to figure out all >> information about the name. The declaration analysis will add the >> definition of "func" to the symbol table, so you can look it up >> ("env.lookup('func')") from that point on. >> >> Does that help? >> >> Stefan > > I want to generate standard python function from "cdef extern from" > function, but I need to annotate these function as they may require a > special treatment (for passing value by reference), also, I may turn C > macros into a call to a C function returning the macro itself. > > cdef extern from "stdio.h": > cdef int BUFSIZ > > Will be turned into : > > def get_BUFSIZ(): > # whatever > > So I need to turn every access to BUFSIZ into a function call. Sounds to me like you should attach the necessary information to the symbol table entry when analysing he "external" declaration. We currently store a "cname", so adding something like a property name or accessor information should fit your use case. We may want to reserve a separate namespace for Python output related information, though. Maybe something like "entry.pybackend.*"? Also, we considered having module level properties at some point. That may fall into the same bucket. What should happen for cimported declarations? Will they be handled in the same way as internally defined "external" declarations? I guess so, even if they may be shared between modules. Stefan From romain.py at gmail.com Tue May 24 22:36:17 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Tue, 24 May 2011 21:36:17 +0100 Subject: [Cython] Scope resolution in a Visitor In-Reply-To: <4DDC0FFA.206@behnel.de> References: <20110523183333.GA5154@ubuntu> <4DDB3A73.4080808@behnel.de> <20110524172239.GA12632@ubuntu> <4DDC0FFA.206@behnel.de> Message-ID: <20110524203617.GA6001@ubuntu> > Sounds to me like you should attach the necessary information to the > symbol table entry when analysing he "external" declaration. That's what I wanted to do that's why I asked how I could access the external declaration node > We currently store a "cname", so adding something like a property name > or accessor information should fit your use case. We may want to > reserve a separate namespace for Python output related information, > though. Maybe something like "entry.pybackend.*"? This would be a clean way to do it > Also, we considered having module level properties at some point. > That may fall into the same bucket. Writing a transformation for that should be relatively straightforward. > What should happen for cimported declarations? Will they be handled > in the same way as internally defined "external" declarations? I > guess so, even if they may be shared between modules. There's 2 possibilities I think : - For each file we generate the wrapping functions - For each pxd file, generate a file containing the wrapping functions Romain From stefan_ml at behnel.de Tue May 24 23:04:28 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 24 May 2011 23:04:28 +0200 Subject: [Cython] CF and finally clause In-Reply-To: References: Message-ID: <4DDC1D5C.3010604@behnel.de> Robert Bradshaw, 24.05.2011 22:07: > On Tue, May 24, 2011 at 12:33 PM, Vitja Makarov wrote: >> When I create control flow graph I have to visit finally clause twice. >> This is required because of different outputs should be generated for >> success and exception case: >> >> try: >> a = might_raise() >> finally: >> pass # 'a' might be uninitialized here >> print(a) # and definitely defined here >> >> So after tracking both cases I have to merge states back because same >> code is generated for each. Note that there are also the break, continue and return cases. >> Maybe it's a good idea to split success/exception case by copying it >> at PostParse transform? > > -1 > > I don't see any difference compared to merging the states from > > if b: > a = None > else: > # don't assign to a The difference is that try-finally executes the exact same code in both cases, but both cases are otherwise in completely distinct code paths. In a way, it's the opposite of your example, where the same outer code path can execute either of the distinct inner code sections. I'm not so opposed to this proposal. I have been (idly and unfoundedly) wondering basically forever if the current way try-finally is implemented is actually a good one. I can accept a performance penalty for the exception case in both try-finally and try-except, but the normal case in try-finally should run as fast as possible. I'm not sure the C compiler can always detect what that "normal" case is in order to properly optimise for it. However, given that there are actually up to four normal cases and only one exception case, I also wonder if even Cython can detect what the "normal" case should be, and if it's really worth providing a distinct implementation in order to optimise it. Stefan From stefan_ml at behnel.de Tue May 24 23:15:04 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Tue, 24 May 2011 23:15:04 +0200 Subject: [Cython] Scope resolution in a Visitor In-Reply-To: <20110524203617.GA6001@ubuntu> References: <20110523183333.GA5154@ubuntu> <4DDB3A73.4080808@behnel.de> <20110524172239.GA12632@ubuntu> <4DDC0FFA.206@behnel.de> <20110524203617.GA6001@ubuntu> Message-ID: <4DDC1FD8.2030402@behnel.de> Romain Guillebert, 24.05.2011 22:36: >> Sounds to me like you should attach the necessary information to the >> symbol table entry when analysing he "external" declaration. > > That's what I wanted to do that's why I asked how I could access the > external declaration node Then you should have asked that in the first place. There are declarator nodes for external declarations. You can traverse them just like any other node. However, they get removed after declaration analysis, so you need to have extracted all required information at that point. Maybe you can just replace them by new nodes that implement the C access for a specific external declaration? >> We currently store a "cname", so adding something like a property name >> or accessor information should fit your use case. We may want to >> reserve a separate namespace for Python output related information, >> though. Maybe something like "entry.pybackend.*"? > > This would be a clean way to do it > >> Also, we considered having module level properties at some point. >> That may fall into the same bucket. > > Writing a transformation for that should be relatively straightforward. Well, for the C code that Cython generates, it means that we first need to implement our own module type in order to support properties at all... >> What should happen for cimported declarations? Will they be handled >> in the same way as internally defined "external" declarations? I >> guess so, even if they may be shared between modules. > > There's 2 possibilities I think : > - For each file we generate the wrapping functions > - For each pxd file, generate a file containing the wrapping functions Right. I don't see a problem with any of the two, nor a major advantage on either side. The first sounds a bit simpler. Stefan From carl.witty at gmail.com Tue May 24 23:17:40 2011 From: carl.witty at gmail.com (Carl Witty) Date: Tue, 24 May 2011 14:17:40 -0700 Subject: [Cython] CF and finally clause In-Reply-To: <4DDC1D5C.3010604@behnel.de> References: <4DDC1D5C.3010604@behnel.de> Message-ID: On Tue, May 24, 2011 at 2:04 PM, Stefan Behnel wrote: > I'm not so opposed to this proposal. I have been (idly and unfoundedly) > wondering basically forever if the current way try-finally is implemented is > actually a good one. I can accept a performance penalty for the exception > case in both try-finally and try-except, but the normal case in try-finally > should run as fast as possible. I'm not sure the C compiler can always > detect what that "normal" case is in order to properly optimise for it. Evidently Java compilers duplicate the finally block (or, actually, triplicate it): http://cliffhacks.blogspot.com/2008/02/java-6-tryfinally-compilation-without.html Carl From robertwb at math.washington.edu Wed May 25 01:30:12 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Tue, 24 May 2011 16:30:12 -0700 Subject: [Cython] CF and finally clause In-Reply-To: References: <4DDC1D5C.3010604@behnel.de> Message-ID: On Tue, May 24, 2011 at 2:17 PM, Carl Witty wrote: > On Tue, May 24, 2011 at 2:04 PM, Stefan Behnel wrote: >> I'm not so opposed to this proposal. I have been (idly and unfoundedly) >> wondering basically forever if the current way try-finally is implemented is >> actually a good one. I can accept a performance penalty for the exception >> case in both try-finally and try-except, but the normal case in try-finally >> should run as fast as possible. I'm not sure the C compiler can always >> detect what that "normal" case is in order to properly optimise for it. > > Evidently Java compilers duplicate the finally block (or, actually, > triplicate it): > > http://cliffhacks.blogspot.com/2008/02/java-6-tryfinally-compilation-without.html Interesting... I don't like the idea of copying code all over, Stefan makes some good points. - Robert From stefan_ml at behnel.de Wed May 25 07:21:26 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Wed, 25 May 2011 07:21:26 +0200 Subject: [Cython] CF and finally clause In-Reply-To: References: <4DDC1D5C.3010604@behnel.de> Message-ID: <4DDC91D6.8090402@behnel.de> Robert Bradshaw, 25.05.2011 01:30: > On Tue, May 24, 2011 at 2:17 PM, Carl Witty wrote: >> On Tue, May 24, 2011 at 2:04 PM, Stefan Behnel wrote: >>> I'm not so opposed to this proposal. I have been (idly and unfoundedly) >>> wondering basically forever if the current way try-finally is implemented is >>> actually a good one. I can accept a performance penalty for the exception >>> case in both try-finally and try-except, but the normal case in try-finally >>> should run as fast as possible. I'm not sure the C compiler can always >>> detect what that "normal" case is in order to properly optimise for it. >> >> Evidently Java compilers duplicate the finally block (or, actually, >> triplicate it): >> >> http://cliffhacks.blogspot.com/2008/02/java-6-tryfinally-compilation-without.html > > Interesting... > > I don't like the idea of copying code all over, Stefan makes some good points. Note that we generate slightly different code for the good and bad cases anyway. Only the exception case stores away and restores the exception, the other ones don't need to do that. I also dislike code duplication in general, but finally clauses tend to be really short. Most of the time, it's just a couple of lines of cleanup code, often just a single function/method call ("file.close()"). In a Cython context, it's even better because many of the finally clauses will just do C cleanup ("free()"), without major Python operations that would bloat the generated code with C-API calls or optimistic code paths. For example, I can't remember having ever seen for-loops or tuple unpacking in a finally clause, which are the things (apart from Python argument unpacking) that Cython generates the longest code for. All that a finally clause really gives you is to make sure the body gets started. If it raises an exception itself, you're on your own again. So I'd rather expect to find try-except(-pass) inside of a finally clause than a nested try-finally, which makes recursive code explosion rather unlikely. I just looked through lxml's sources and found that out of 36 finally clauses, 26 (more than 2/3) are one-liners like "thing.close()", "free(mem)" or "self.attr = None". Only two clauses are longer than three lines because they do different things in Py2 and Py3 (so the C compiler will drop part of it), everything else is basically just a permutation of the above three statements or an if-test before cleanup. A quick skip through the stdlib seems to second that: lots of one liners, some if-tests, very few other cases. Longer blocks are truly rare, such as in the dummy threading module, which has a lengthy "if+cleanup" finally clause at the module scope, or the subprocess module, which has one 4-step "if+cleanup" section (obviously in the Windows code ;) ). IMHO, not really worth bothering about. I think that programmers tend to be rather aware of what belongs into a finally clause and what doesn't really need to go there, either because they know that this will get executed in all possible cases, so it should only be the strict intersection of the different code paths - or simply because "finally" seems too mystical to entrust it with larger code blocks. Stefan From vitja.makarov at gmail.com Wed May 25 08:19:29 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 25 May 2011 10:19:29 +0400 Subject: [Cython] subclassing list Message-ID: cdef class Foo(list): pass def foo(): f = Foo() f.append(1) gcc -g3 -fPIC -I/usr/include/python2.6 -g3 -W -Wall -c -o lll.o lll.c lll.c: In function ?__pyx_pf_3lll_foo?: lll.c:468: error: ?struct __pyx_obj_3lll_Foo? has no member named ?None? Is this a known bug? -- vitja. From vitja.makarov at gmail.com Wed May 25 20:04:09 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Wed, 25 May 2011 22:04:09 +0400 Subject: [Cython] Small issue with buffers Message-ID: Hi! Trying to fix some tests broken by CF I've found this issue: def fuu(object[int] b1): cdef object[int] b2 print b1 buff.c: In function ?__pyx_pf_4buff_fuu?: buff.c:504: error: ?__pyx_bstruct_b2? undeclared (first use in this function) buff.c:504: error: (Each undeclared identifier is reported only once buff.c:504: error: for each function it appears in.) buff.c: In function ?__Pyx_BufFmt_TypeCharToAlignment?: buff.c:809: warning: unused parameter ?is_complex? -- vitja. From robertwb at math.washington.edu Wed May 25 21:51:10 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Wed, 25 May 2011 12:51:10 -0700 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: References: Message-ID: On Wed, May 25, 2011 at 12:37 PM, jpe wrote: > This optimizes startswith / endwith optimization for str. Cool. >What's unclear to me is how str will be mapped to either bytes or unicode; I assume at some point cython will have a python3 syntax mode where str is unicode, print is a function, etc (if it doesn't have one already). ?Should I be using the type name bytes instead of str? I'm glad you're thinking about this question, some explanation of the various string types is at http://wiki.cython.org/enhancements/stringliterals Probably the way to do this is have one optimization for bytes, one for unicode, and then have a third type for str that dispatches to the one or the other depending on the python version (using #define). - Robert From jpe at wingware.com Wed May 25 22:41:29 2011 From: jpe at wingware.com (John Ehresman) Date: Wed, 25 May 2011 16:41:29 -0400 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: References: Message-ID: <4DDD6979.2080100@wingware.com> On 5/25/11 3:51 PM, Robert Bradshaw wrote: > I'm glad you're thinking about this question, some explanation of the > various string types is at > http://wiki.cython.org/enhancements/stringliterals > > Probably the way to do this is have one optimization for bytes, one > for unicode, and then have a third type for str that dispatches to the > one or the other depending on the python version (using #define). I think this means that the current unicode optimizations aren't used when variables are declared as str and a python 3 runtime is used. Should all unicode optimizations support str eventually? Thanks, John From robertwb at math.washington.edu Wed May 25 22:52:21 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Wed, 25 May 2011 13:52:21 -0700 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDD6979.2080100@wingware.com> References: <4DDD6979.2080100@wingware.com> Message-ID: On Wed, May 25, 2011 at 1:41 PM, John Ehresman wrote: > On 5/25/11 3:51 PM, Robert Bradshaw wrote: >> >> I'm glad you're thinking about this question, some explanation of the >> various string types is at >> http://wiki.cython.org/enhancements/stringliterals >> >> Probably the way to do this is have one optimization for bytes, one >> for unicode, and then have a third type for str that dispatches to the >> one or the other depending on the python version (using #define). > > I think this means that the current unicode optimizations aren't used when > variables are declared as str and a python 3 runtime is used. Should all > unicode optimizations support str eventually? Yes. From stefan_ml at behnel.de Thu May 26 09:21:34 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 26 May 2011 09:21:34 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: References: Message-ID: <4DDDFF7E.2090309@behnel.de> jpe, 25.05.2011 21:37: > This optimizes startswith / endwith optimization for str. What's > unclear to me is how str will be mapped to either bytes or unicode > Should I be using the type name bytes instead of str? Different things. Robert already pointed you to the Wiki site. Basically, "str" is evaluated at C compile time to become either bytes or unicode, depending on the CPython version it is being compiled against. The same applies to literals. (And believe me, there has gone some work into this behaviour...) > I assume at some point cython will have a python3 syntax mode where str is > unicode, print is a function, etc (if it doesn't have one already). We have both a "-3" command line option and the "language_level=3" compiler directive for that. Stefan From stefan_ml at behnel.de Thu May 26 09:27:49 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 26 May 2011 09:27:49 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: References: <4DDD6979.2080100@wingware.com> Message-ID: <4DDE00F5.8030003@behnel.de> Robert Bradshaw, 25.05.2011 22:52: > On Wed, May 25, 2011 at 1:41 PM, John Ehresman wrote: >> On 5/25/11 3:51 PM, Robert Bradshaw wrote: >>> >>> I'm glad you're thinking about this question, some explanation of the >>> various string types is at >>> http://wiki.cython.org/enhancements/stringliterals >>> >>> Probably the way to do this is have one optimization for bytes, one >>> for unicode, and then have a third type for str that dispatches to the >>> one or the other depending on the python version (using #define). >> >> I think this means that the current unicode optimizations aren't used when >> variables are declared as str and a python 3 runtime is used. Should all >> unicode optimizations support str eventually? > > Yes. Well, minus those that are not portable. For example, the return type of indexing and iteration is the C type "Py_UCS4" for unicode, but the Python type "str" (i.e. bytes/unicode) for "str". I also didn't take a thorough look through the C-API functions for the str type in Py2 and Py3. Things certainly become more ugly when trying to optimise Python code into C for both platforms, than when leaving things at the Python type level. Stefan From robertwb at math.washington.edu Thu May 26 09:40:11 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Thu, 26 May 2011 00:40:11 -0700 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDE00F5.8030003@behnel.de> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> Message-ID: On Thu, May 26, 2011 at 12:27 AM, Stefan Behnel wrote: > Robert Bradshaw, 25.05.2011 22:52: >> >> On Wed, May 25, 2011 at 1:41 PM, John Ehresman wrote: >>> >>> On 5/25/11 3:51 PM, Robert Bradshaw wrote: >>>> >>>> I'm glad you're thinking about this question, some explanation of the >>>> various string types is at >>>> http://wiki.cython.org/enhancements/stringliterals >>>> >>>> Probably the way to do this is have one optimization for bytes, one >>>> for unicode, and then have a third type for str that dispatches to the >>>> one or the other depending on the python version (using #define). >>> >>> I think this means that the current unicode optimizations aren't used >>> when >>> variables are declared as str and a python 3 runtime is used. Should all >>> unicode optimizations support str eventually? >> >> Yes. > > Well, minus those that are not portable. For example, the return type of > indexing and iteration is the C type "Py_UCS4" for unicode, but the Python > type "str" (i.e. bytes/unicode) for "str". I also didn't take a thorough > look through the C-API functions for the str type in Py2 and Py3. Things > certainly become more ugly when trying to optimise Python code into C for > both platforms, than when leaving things at the Python type level. I was referring to Python-level things like startswith. On this note, the pattern of swapping out builtin methods (and perhaps functions) with more optimized C versions is something that perhaps it would be good to be able to do more generally, rather than hard coding the list into Optimize.py. We floated such "overlay" ideas way back in the day. - Robert From stefan_ml at behnel.de Thu May 26 10:12:03 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 26 May 2011 10:12:03 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> Message-ID: <4DDE0B53.7050306@behnel.de> Robert Bradshaw, 26.05.2011 09:40: > the pattern of swapping out builtin methods (and perhaps > functions) with more optimized C versions is something that perhaps it > would be good to be able to do more generally, rather than hard coding > the list into Optimize.py. Right. All that would really be needed is a way to define default values for arguments of builtin methods. Then most of the method optimisations could be moved into Builtin.py. Stefan From d.s.seljebotn at astro.uio.no Thu May 26 10:24:17 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Thu, 26 May 2011 10:24:17 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDE0B53.7050306@behnel.de> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> <4DDE0B53.7050306@behnel.de> Message-ID: <4DDE0E31.9070203@astro.uio.no> On 05/26/2011 10:12 AM, Stefan Behnel wrote: > Robert Bradshaw, 26.05.2011 09:40: >> the pattern of swapping out builtin methods (and perhaps >> functions) with more optimized C versions is something that perhaps it >> would be good to be able to do more generally, rather than hard coding >> the list into Optimize.py. > > Right. All that would really be needed is a way to define default values > for arguments of builtin methods. Then most of the method optimisations > could be moved into Builtin.py. BTW, the idea of the overlay stuff Robert referred to was that we could add syntax to pxd files so that the "unicode" type and its alternative method implementations could be fleshed out in a pxd file (and the same with other standard library or third-party types that are not written with Cython support in mind, but may have a C API that we want to dispatch to instead of their Python API). Dag Sverre From stefan_ml at behnel.de Thu May 26 10:43:51 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 26 May 2011 10:43:51 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDE0E31.9070203@astro.uio.no> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> <4DDE0B53.7050306@behnel.de> <4DDE0E31.9070203@astro.uio.no> Message-ID: <4DDE12C7.9030601@behnel.de> Dag Sverre Seljebotn, 26.05.2011 10:24: > On 05/26/2011 10:12 AM, Stefan Behnel wrote: >> Robert Bradshaw, 26.05.2011 09:40: >>> the pattern of swapping out builtin methods (and perhaps >>> functions) with more optimized C versions is something that perhaps it >>> would be good to be able to do more generally, rather than hard coding >>> the list into Optimize.py. >> >> Right. All that would really be needed is a way to define default values >> for arguments of builtin methods. Then most of the method optimisations >> could be moved into Builtin.py. > > BTW, the idea of the overlay stuff Robert referred to was that we could add > syntax to pxd files so that the "unicode" type and its alternative method > implementations could be fleshed out in a pxd file (and the same with other > standard library or third-party types that are not written with Cython > support in mind, but may have a C API that we want to dispatch to instead > of their Python API). Well, dispatching to existing C-API functions is easy and can be done in Builtin.py. Moving that to .pxd files or not is a minor detail. The problems, as in this case, are that we often need to implement our own C-API and that we need to match defaulted arguments to suitable default values. I guess this could be done with inline methods, once we have something like overlay types in .pxd files. What's the status of Cython implemented utility code, BTW? Stefan From d.s.seljebotn at astro.uio.no Thu May 26 10:55:44 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Thu, 26 May 2011 10:55:44 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDE12C7.9030601@behnel.de> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> <4DDE0B53.7050306@behnel.de> <4DDE0E31.9070203@astro.uio.no> <4DDE12C7.9030601@behnel.de> Message-ID: <4DDE1590.2060107@astro.uio.no> On 05/26/2011 10:43 AM, Stefan Behnel wrote: > Dag Sverre Seljebotn, 26.05.2011 10:24: >> On 05/26/2011 10:12 AM, Stefan Behnel wrote: >>> Robert Bradshaw, 26.05.2011 09:40: >>>> the pattern of swapping out builtin methods (and perhaps >>>> functions) with more optimized C versions is something that perhaps it >>>> would be good to be able to do more generally, rather than hard coding >>>> the list into Optimize.py. >>> >>> Right. All that would really be needed is a way to define default values >>> for arguments of builtin methods. Then most of the method optimisations >>> could be moved into Builtin.py. >> >> BTW, the idea of the overlay stuff Robert referred to was that we >> could add >> syntax to pxd files so that the "unicode" type and its alternative method >> implementations could be fleshed out in a pxd file (and the same with >> other >> standard library or third-party types that are not written with Cython >> support in mind, but may have a C API that we want to dispatch to instead >> of their Python API). > > Well, dispatching to existing C-API functions is easy and can be done in > Builtin.py. Moving that to .pxd files or not is a minor detail. The > problems, as in this case, are that we often need to implement our own > C-API and that we need to match defaulted arguments to suitable default > values. I guess this could be done with inline methods, once we have > something like overlay types in .pxd files. > > What's the status of Cython implemented utility code, BTW? It's still bit-rotting in Kurt's branch, but it is working there. The plans are that I set aside a couple of days in June for merging that branch. I need to do so before Mark resumes his GSoC in July, so there's some pressure on me to finally get it done. Dag Sverre From robertwb at math.washington.edu Thu May 26 17:40:39 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Thu, 26 May 2011 08:40:39 -0700 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDE12C7.9030601@behnel.de> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> <4DDE0B53.7050306@behnel.de> <4DDE0E31.9070203@astro.uio.no> <4DDE12C7.9030601@behnel.de> Message-ID: On Thu, May 26, 2011 at 1:43 AM, Stefan Behnel wrote: > Dag Sverre Seljebotn, 26.05.2011 10:24: >> >> On 05/26/2011 10:12 AM, Stefan Behnel wrote: >>> >>> Robert Bradshaw, 26.05.2011 09:40: >>>> >>>> the pattern of swapping out builtin methods (and perhaps >>>> functions) with more optimized C versions is something that perhaps it >>>> would be good to be able to do more generally, rather than hard coding >>>> the list into Optimize.py. >>> >>> Right. All that would really be needed is a way to define default values >>> for arguments of builtin methods. Then most of the method optimisations >>> could be moved into Builtin.py. >> >> BTW, the idea of the overlay stuff Robert referred to was that we could >> add >> syntax to pxd files so that the "unicode" type and its alternative method >> implementations could be fleshed out in a pxd file (and the same with >> other >> standard library or third-party types that are not written with Cython >> support in mind, but may have a C API that we want to dispatch to instead >> of their Python API). > > Well, dispatching to existing C-API functions is easy and can be done in > Builtin.py. Moving that to .pxd files or not is a minor detail. The > problems, as in this case, are that we often need to implement our own C-API > and that we need to match defaulted arguments to suitable default values. I > guess this could be done with inline methods, once we have something like > overlay types in .pxd files. Yes, I was thinking that many of these could be implemented in Cython. We sometimes do tricky stuff with #defines though, but usually on the Python version which could possibly be supported somehow (?). At least, as we move away from the low-level ones and start expanding, implementing them in Cython makes more and more sense. > What's the status of Cython implemented utility code, BTW? > > Stefan > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From jpe at wingware.com Thu May 26 22:02:08 2011 From: jpe at wingware.com (John Ehresman) Date: Thu, 26 May 2011 16:02:08 -0400 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDE00F5.8030003@behnel.de> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> Message-ID: <4DDEB1C0.1040703@wingware.com> On 5/26/11 3:27 AM, Stefan Behnel wrote: >>> I think this means that the current unicode optimizations aren't used >>> when >>> variables are declared as str and a python 3 runtime is used. Should all >>> unicode optimizations support str eventually? >> >> Yes. > > Well, minus those that are not portable. For example, the return type of > indexing and iteration is the C type "Py_UCS4" for unicode, but the > Python type "str" (i.e. bytes/unicode) for "str". I also didn't take a > thorough look through the C-API functions for the str type in Py2 and > Py3. Things certainly become more ugly when trying to optimise Python > code into C for both platforms, than when leaving things at the Python > type level. Would it work for these methods to return Py_UCS4 in all 3 cases (unicode, bytes, str)? In the bytes case, the multibyte int would simply be cast to char if that was what it was assigned to but the value wouldn't be above 255 in any case. The case I worry about is losing optimizations w/ a Python3 runtime if str is used rather than unicode. John From stefan_ml at behnel.de Thu May 26 23:43:35 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 26 May 2011 23:43:35 +0200 Subject: [Cython] [cython] Initial startswith / endswith optimization (#35) In-Reply-To: <4DDEB1C0.1040703@wingware.com> References: <4DDD6979.2080100@wingware.com> <4DDE00F5.8030003@behnel.de> <4DDEB1C0.1040703@wingware.com> Message-ID: <4DDEC987.2060500@behnel.de> John Ehresman, 26.05.2011 22:02: > On 5/26/11 3:27 AM, Stefan Behnel wrote: >>>> I think this means that the current unicode optimizations aren't used >>>> when >>>> variables are declared as str and a python 3 runtime is used. Should all >>>> unicode optimizations support str eventually? >>> >>> Yes. >> >> Well, minus those that are not portable. For example, the return type of >> indexing and iteration is the C type "Py_UCS4" for unicode, but the >> Python type "str" (i.e. bytes/unicode) for "str". I also didn't take a >> thorough look through the C-API functions for the str type in Py2 and >> Py3. Things certainly become more ugly when trying to optimise Python >> code into C for both platforms, than when leaving things at the Python >> type level. > > Would it work for these methods to return Py_UCS4 in all 3 cases (unicode, > bytes, str)? There are two sides to this: what the C compiler eventually sees and what Cython makes of the types internally. Letting Cython assume that the result is Py_UCS4 is incorrect in the Py2 case. Amongst other problems, it would make the value turn into a unicode string when coercing to a Python object. > In the bytes case, the multibyte int would simply be cast to char if > that was what it was assigned to but the value wouldn't be above 255 in > any case. Sure it could, "str" is unicode in Py3, so you get a Unicode string with all possible values, e.g. when using unicode escapes. > The case I worry about is losing optimizations w/ a Python3 runtime if str > is used rather than unicode. You should expect that. If you want optimised code, use a suitable type. Stefan From stefan_ml at behnel.de Fri May 27 09:41:05 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Fri, 27 May 2011 09:41:05 +0200 Subject: [Cython] Broken tests Message-ID: <4DDF5591.8060602@behnel.de> Hi, could we please make it a requirement to run the complete test suite after a branch merge? Or at least taking a close look at Jenkins after pushing a merge? And then fixing the bugs it finds? Stefan From vitja.makarov at gmail.com Fri May 27 14:41:39 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Fri, 27 May 2011 16:41:39 +0400 Subject: [Cython] Broken tests In-Reply-To: <4DDF5591.8060602@behnel.de> References: <4DDF5591.8060602@behnel.de> Message-ID: 2011/5/27 Stefan Behnel : > Hi, > > could we please make it a requirement to run the complete test suite after a > branch merge? Or at least taking a close look at Jenkins after pushing a > merge? And then fixing the bugs it finds? > > Stefan > There are failing tests in _control_flow branch. I guess it's better to fix them after merge. -- vitja. From d.s.seljebotn at astro.uio.no Fri May 27 15:00:01 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 27 May 2011 15:00:01 +0200 Subject: [Cython] Broken tests In-Reply-To: References: <4DDF5591.8060602@behnel.de> Message-ID: <4DDFA051.4070407@astro.uio.no> On 05/27/2011 02:41 PM, Vitja Makarov wrote: > 2011/5/27 Stefan Behnel: >> Hi, >> >> could we please make it a requirement to run the complete test suite after a >> branch merge? Or at least taking a close look at Jenkins after pushing a >> merge? And then fixing the bugs it finds? >> >> Stefan >> > > There are failing tests in _control_flow branch. > I guess it's better to fix them after merge. Wouldn't it be better to rebase _control_flow on master, then fix tests, then merge it into master? (Replace "rebase" with "merge in master" if you wish, I'm going by the _ prefix here.) Dag Sverre From vitja.makarov at gmail.com Fri May 27 15:16:28 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Fri, 27 May 2011 17:16:28 +0400 Subject: [Cython] Broken tests In-Reply-To: <4DDFA051.4070407@astro.uio.no> References: <4DDF5591.8060602@behnel.de> <4DDFA051.4070407@astro.uio.no> Message-ID: 2011/5/27 Dag Sverre Seljebotn : > On 05/27/2011 02:41 PM, Vitja Makarov wrote: >> >> 2011/5/27 Stefan Behnel: >>> >>> Hi, >>> >>> could we please make it a requirement to run the complete test suite >>> after a >>> branch merge? Or at least taking a close look at Jenkins after pushing a >>> merge? And then fixing the bugs it finds? >>> >>> Stefan >>> >> >> There are failing tests in _control_flow branch. >> I guess it's better to fix them after merge. > > Wouldn't it be better to rebase _control_flow on master, then fix tests, > then merge it into master? > > (Replace "rebase" with "merge in master" if you wish, I'm going by the _ > prefix here.) > Sure. But I think that I need some help to make decision which tests should be fixed and which removed. -- vitja. From stefan_ml at behnel.de Fri May 27 15:54:47 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Fri, 27 May 2011 15:54:47 +0200 Subject: [Cython] [cython] Openmp (#30) In-Reply-To: References: Message-ID: <4DDFAD27.5090106@behnel.de> [regarding the code for analysing uninitialised variables in the OpenMP branch] dagss, 27.05.2011 10:32: > I suggest this: > > a) Vitja and Stefan notifies Mark of any issues that stops control flow > analysis from going into trunk (outright collisions etc.). Those have > prioritiy over fused types work etc (although I guess Mark don't have > much GSoC time the next month). > > b) Come July, when control flow analysis is presumably in master, Mark > takes a pass and removes any duplicated logic. > > Thoughts? I don't think there are any collisions, it's just that Vitja is currently removing the old visitor based attempts of doing variable initialisation analysis. Getting yet another one in while getting rid of the old ones is a rather unnecessary duplication of effort. I suggest we rebase Vitja's branch when the current test issues are solved, then we'll see if there are any issues with the parallel looping code. I'm in favour of merging the control flow branch ASAP, simply because it's such a great feature. I already disabled two tests in Mark's code that relied on uninitialised variables being None. There are likely others (way older ones) that were written with such misfeatures in mind. Stefan From d.s.seljebotn at astro.uio.no Fri May 27 16:15:12 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 27 May 2011 16:15:12 +0200 Subject: [Cython] [cython] Openmp (#30) In-Reply-To: <4DDFAD27.5090106@behnel.de> References: <4DDFAD27.5090106@behnel.de> Message-ID: <4DDFB1F0.9030800@astro.uio.no> On 05/27/2011 03:54 PM, Stefan Behnel wrote: > [regarding the code for analysing uninitialised variables in the OpenMP > branch] > > dagss, 27.05.2011 10:32: >> I suggest this: >> >> a) Vitja and Stefan notifies Mark of any issues that stops control flow >> analysis from going into trunk (outright collisions etc.). Those have >> prioritiy over fused types work etc (although I guess Mark don't have >> much GSoC time the next month). >> >> b) Come July, when control flow analysis is presumably in master, Mark >> takes a pass and removes any duplicated logic. >> >> Thoughts? > > I don't think there are any collisions, it's just that Vitja is > currently removing the old visitor based attempts of doing variable > initialisation analysis. Getting yet another one in while getting rid of > the old ones is a rather unnecessary duplication of effort. Well, what's done is done. We can try to be smarter in the future. Dag Sverre From vitja.makarov at gmail.com Fri May 27 16:27:48 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Fri, 27 May 2011 18:27:48 +0400 Subject: [Cython] Control Flow Message-ID: I've recently fixed some issues: - closure variables were not tracked - scoped expression variables were initialized to None So, I should fix broken tests, here are some of them: nogil (should be fixed) purecdef (upstream) cfunc_directive_in_pyclass (upstream) bufaccess_noassignT444 (should be removed?) bufaccess (should be fixed) ass2longlong (should be fixed) builtinfuncs (should be fixed) extcmethcall (should be fixed) extcoerce (fixed or removed?) e_extweakref (should be fixed) -- vitja. From d.s.seljebotn at astro.uio.no Fri May 27 16:37:20 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Fri, 27 May 2011 16:37:20 +0200 Subject: [Cython] Control Flow In-Reply-To: References: Message-ID: <4DDFB720.6070307@astro.uio.no> On 05/27/2011 04:27 PM, Vitja Makarov wrote: > I've recently fixed some issues: > > - closure variables were not tracked > - scoped expression variables were initialized to None > > So, I should fix broken tests, here are some of them: > > nogil (should be fixed) > purecdef (upstream) > cfunc_directive_in_pyclass (upstream) > bufaccess_noassignT444 (should be removed?) One could make it an error testcase instead, trapping the syntax error you now raise. Depends on how confident you are on new control flow tests and whether buffers are tested there. > bufaccess (should be fixed) Yeah, feel free to just remove nousage() and printbuf(). > ass2longlong (should be fixed) > builtinfuncs (should be fixed) > extcmethcall (should be fixed) > extcoerce (fixed or removed?) > e_extweakref (should be fixed) > Dag From markflorisson88 at gmail.com Fri May 27 16:56:11 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Fri, 27 May 2011 16:56:11 +0200 Subject: [Cython] [cython] Openmp (#30) In-Reply-To: <4DDFB1F0.9030800@astro.uio.no> References: <4DDFAD27.5090106@behnel.de> <4DDFB1F0.9030800@astro.uio.no> Message-ID: On 27 May 2011 16:15, Dag Sverre Seljebotn wrote: > On 05/27/2011 03:54 PM, Stefan Behnel wrote: >> >> [regarding the code for analysing uninitialised variables in the OpenMP >> branch] >> >> dagss, 27.05.2011 10:32: >>> >>> I suggest this: >>> >>> a) Vitja and Stefan notifies Mark of any issues that stops control flow >>> analysis from going into trunk (outright collisions etc.). Those have >>> prioritiy over fused types work etc (although I guess Mark don't have >>> much GSoC time the next month). >>> >>> b) Come July, when control flow analysis is presumably in master, Mark >>> takes a pass and removes any duplicated logic. >>> >>> Thoughts? >> >> I don't think there are any collisions, it's just that Vitja is >> currently removing the old visitor based attempts of doing variable >> initialisation analysis. Getting yet another one in while getting rid of >> the old ones is a rather unnecessary duplication of effort. > > Well, what's done is done. We can try to be smarter in the future. > > Dag Sverre > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > Fortunately, the effort was rather small as it was a very simplistic way to detect uninitialized variables. I don't mind wasting 30 lines for a stopgap solution. And the good thing about it is that when the control flow branch gets merged the error tests are already written. From jpe at wingware.com Fri May 27 21:55:37 2011 From: jpe at wingware.com (John Ehresman) Date: Fri, 27 May 2011 15:55:37 -0400 Subject: [Cython] Bug in ord(Py_UNICODE) optimization Message-ID: <4DE001B9.30806@wingware.com> Hi, ord() applied to a Py_UNICODE typed variable seems to yield a 1 character unicode string rather than an integer. The following doctest fails when added to unicodefunction.pyx: def Py_UNICODE_ord(unicode s): """ >>> Py_UNICODE_ord(u' ') 32 """ cdef Py_UNICODE u u = s[0] return ord(u) Thanks, John From stefan_ml at behnel.de Sat May 28 00:32:46 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 00:32:46 +0200 Subject: [Cython] Redundant Cython exception message strings Message-ID: <4DE0268E.8040401@behnel.de> Hi, I recently stumbled over a tradeoff question with AttributeError, and now found the same situation for UnboundLocalError in Vitja's control flow branch. So here it is. When we raise an exception several times in different parts of the code with a message that only differs slightly each time (usually something like "'NoneType' has no attribute X", or "local variable X referenced before assignment"), we have three choices to handle this: 1) Optimise for speed: create a Python string object at module initialisation time and call PyErr_SetObject(exc_type, msg_str_obj). 2) Current way: let CPython create the string object when raising the exception and just call PyErr_SetString(exc_type, "complete message"). 3) Trade speed for size and allow the C compiler to reduce the storage redundancy: write only the message template and the names as C char* constants by calling PyErr_Format(exc_type, "message template %s", "X"). Assuming that exceptions should be exceptional, I'm leaning towards 3). This would allow the C compiler to collapse multiple usages of the same C string into one data constant, thus reducing a bit of redundancy in the shared library size and the memory footprint. However, it would (slightly?) slow down the exception raising due to the additional string formatting, even when compared to the need to build a Python string object that it shares with 2). While 1) would obviously be the fastest way to raise an exception (no memory allocation, only refcounting), I think it's not worth it for exceptions as it increases both the runtime memory overhead and the module startup time. Thoughts? Stefan From robertwb at math.washington.edu Sat May 28 00:39:36 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Fri, 27 May 2011 15:39:36 -0700 Subject: [Cython] Redundant Cython exception message strings In-Reply-To: <4DE0268E.8040401@behnel.de> References: <4DE0268E.8040401@behnel.de> Message-ID: On Fri, May 27, 2011 at 3:32 PM, Stefan Behnel wrote: > Hi, > > I recently stumbled over a tradeoff question with AttributeError, and now > found the same situation for UnboundLocalError in Vitja's control flow > branch. So here it is. > > When we raise an exception several times in different parts of the code with > a message that only differs slightly each time (usually something like > "'NoneType' has no attribute X", or "local variable X referenced before > assignment"), we have three choices to handle this: > > 1) Optimise for speed: create a Python string object at module > initialisation time and call PyErr_SetObject(exc_type, msg_str_obj). > > 2) Current way: let CPython create the string object when raising the > exception and just call PyErr_SetString(exc_type, "complete message"). > > 3) Trade speed for size and allow the C compiler to reduce the storage > redundancy: write only the message template and the names as C char* > constants by calling PyErr_Format(exc_type, "message template %s", "X"). > > Assuming that exceptions should be exceptional, I'm leaning towards 3). This > would allow the C compiler to collapse multiple usages of the same C string > into one data constant, thus reducing a bit of redundancy in the shared > library size and the memory footprint. However, it would (slightly?) slow > down the exception raising due to the additional string formatting, even > when compared to the need to build a Python string object that it shares > with 2). While 1) would obviously be the fastest way to raise an exception > (no memory allocation, only refcounting), I think it's not worth it for > exceptions as it increases both the runtime memory overhead and the module > startup time. > > Thoughts? Any back-of-the-envelope calculations on how much the savings would be? I think I'm leaning towards 3 as well, certainly not option 1. - Robert From robertwb at math.washington.edu Sat May 28 01:17:02 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Fri, 27 May 2011 16:17:02 -0700 Subject: [Cython] Broken tests In-Reply-To: References: <4DDF5591.8060602@behnel.de> <4DDFA051.4070407@astro.uio.no> Message-ID: On Fri, May 27, 2011 at 6:16 AM, Vitja Makarov wrote: > 2011/5/27 Dag Sverre Seljebotn : >> On 05/27/2011 02:41 PM, Vitja Makarov wrote: >>> >>> 2011/5/27 Stefan Behnel: >>>> >>>> Hi, >>>> >>>> could we please make it a requirement to run the complete test suite >>>> after a >>>> branch merge? Or at least taking a close look at Jenkins after pushing a >>>> merge? And then fixing the bugs it finds? >>>> >>>> Stefan >>>> >>> >>> There are failing tests in _control_flow branch. >>> I guess it's better to fix them after merge. >> >> Wouldn't it be better to rebase _control_flow on master, then fix tests, >> then merge it into master? +1 >> (Replace "rebase" with "merge in master" if you wish, I'm going by the _ >> prefix here.) >> > > Sure. But I think that I need some help to make decision which tests > should be fixed and which removed. Do you have any specific tests that are unclear? In any case, I think this email was primarily aimed at me, as there was a conflict with the with-gil branch and the pure cdef function branch that I didn't catch before I merged. (I had planned to take a look at the results later, but my day got too crazy...) +1 to the policy of running the entire testsuite on at least one Python before pushing a merge. - Robert From stefan_ml at behnel.de Sat May 28 01:16:25 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 01:16:25 +0200 Subject: [Cython] Bug in ord(Py_UNICODE) optimization In-Reply-To: <4DE001B9.30806@wingware.com> References: <4DE001B9.30806@wingware.com> Message-ID: <4DE030C9.4060205@behnel.de> John Ehresman, 27.05.2011 21:55: > ord() applied to a Py_UNICODE typed variable seems to yield a 1 character > unicode string rather than an integer. The following doctest fails when > added to unicodefunction.pyx: > > def Py_UNICODE_ord(unicode s): > """ > >>> Py_UNICODE_ord(u' ') > 32 > """ > cdef Py_UNICODE u > u = s[0] > return ord(u) ord() is actually unpacked in this case (see Optimise.py), but the result type is incorrect. It's Py_UNICODE (which coerces back to a unicode string), whereas it should be int (thus coercing to a Python integer object). I pushed a fix, and also the obvious optimisation for calling ord() on single character string literals. Thanks for the report. Stefan From robertwb at math.washington.edu Sat May 28 01:34:50 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Fri, 27 May 2011 16:34:50 -0700 Subject: [Cython] Control Flow In-Reply-To: References: Message-ID: On Fri, May 27, 2011 at 7:27 AM, Vitja Makarov wrote: > I've recently fixed some issues: > > ?- closure variables were not tracked > ?- scoped expression variables were initialized to None > > So, I should fix broken tests, here are some of them: > > nogil (should be fixed) > purecdef (upstream) > cfunc_directive_in_pyclass (upstream) > bufaccess_noassignT444 (should be removed?) > bufaccess (should be fixed) > ass2longlong (should be fixed) > builtinfuncs (should be fixed) > extcmethcall (should be fixed) > extcoerce (fixed or removed?) Unless you see this code being exercised elsewhere (a run test would be better her anyways) it's an easy fix that should be done. > e_extweakref (should be fixed) > > -- > vitja. > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > From vitja.makarov at gmail.com Sat May 28 10:15:52 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sat, 28 May 2011 12:15:52 +0400 Subject: [Cython] Redundant Cython exception message strings In-Reply-To: References: <4DE0268E.8040401@behnel.de> Message-ID: 2011/5/28 Robert Bradshaw : > On Fri, May 27, 2011 at 3:32 PM, Stefan Behnel wrote: >> Hi, >> >> I recently stumbled over a tradeoff question with AttributeError, and now >> found the same situation for UnboundLocalError in Vitja's control flow >> branch. So here it is. >> >> When we raise an exception several times in different parts of the code with >> a message that only differs slightly each time (usually something like >> "'NoneType' has no attribute X", or "local variable X referenced before >> assignment"), we have three choices to handle this: >> >> 1) Optimise for speed: create a Python string object at module >> initialisation time and call PyErr_SetObject(exc_type, msg_str_obj). >> >> 2) Current way: let CPython create the string object when raising the >> exception and just call PyErr_SetString(exc_type, "complete message"). >> >> 3) Trade speed for size and allow the C compiler to reduce the storage >> redundancy: write only the message template and the names as C char* >> constants by calling PyErr_Format(exc_type, "message template %s", "X"). >> >> Assuming that exceptions should be exceptional, I'm leaning towards 3). This >> would allow the C compiler to collapse multiple usages of the same C string >> into one data constant, thus reducing a bit of redundancy in the shared >> library size and the memory footprint. However, it would (slightly?) slow >> down the exception raising due to the additional string formatting, even >> when compared to the need to build a Python string object that it shares >> with 2). While 1) would obviously be the fastest way to raise an exception >> (no memory allocation, only refcounting), I think it's not worth it for >> exceptions as it increases both the runtime memory overhead and the module >> startup time. >> >> Thoughts? > > Any back-of-the-envelope calculations on how much the savings would > be? I think I'm leaning towards 3 as well, certainly not option 1. > For UnboundLocalError and NameError I used 2) way: https://github.com/vitek/cython/commit/1fe86b85d965753244cd09db38b1089b40f09a58 So maybe I should add functions like __Pyx_RaiseUnboundLocalError and __Pyx_RaiseClosureNameError that will use 3) way. How do you like put_error_if_unbound CCodeWriter method is that right place for it? -- vitja. From stefan_ml at behnel.de Sat May 28 11:37:23 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 11:37:23 +0200 Subject: [Cython] Redundant Cython exception message strings In-Reply-To: References: <4DE0268E.8040401@behnel.de> Message-ID: <4DE0C253.2020000@behnel.de> Robert Bradshaw, 28.05.2011 00:39: > On Fri, May 27, 2011 at 3:32 PM, Stefan Behnel wrote: >> I recently stumbled over a tradeoff question with AttributeError, and now >> found the same situation for UnboundLocalError in Vitja's control flow >> branch. So here it is. >> >> When we raise an exception several times in different parts of the code with >> a message that only differs slightly each time (usually something like >> "'NoneType' has no attribute X", or "local variable X referenced before >> assignment"), we have three choices to handle this: >> >> 1) Optimise for speed: create a Python string object at module >> initialisation time and call PyErr_SetObject(exc_type, msg_str_obj). >> >> 2) Current way: let CPython create the string object when raising the >> exception and just call PyErr_SetString(exc_type, "complete message"). >> >> 3) Trade speed for size and allow the C compiler to reduce the storage >> redundancy: write only the message template and the names as C char* >> constants by calling PyErr_Format(exc_type, "message template %s", "X"). >> >> Assuming that exceptions should be exceptional, I'm leaning towards 3). This >> would allow the C compiler to collapse multiple usages of the same C string >> into one data constant, thus reducing a bit of redundancy in the shared >> library size and the memory footprint. However, it would (slightly?) slow >> down the exception raising due to the additional string formatting, even >> when compared to the need to build a Python string object that it shares >> with 2). While 1) would obviously be the fastest way to raise an exception >> (no memory allocation, only refcounting), I think it's not worth it for >> exceptions as it increases both the runtime memory overhead and the module >> startup time. > > Any back-of-the-envelope calculations on how much the savings would > be? As a micro benchmark, I wrote three C functions that do 10 exception setting calls and then clear the exception, and called those 10x in a loop (i.e. 100 exceptions). Results: 1) PyErr_SetObject(PyExc_TypeError, Py_None) Py3.3: 1000000 loops, best of 3: 1.42 usec Py2.7: 1000000 loops, best of 3: 0.965 usec 2) PyErr_SetString(PyExc_TypeError, "[complete message]") Py3.3: 100000 loops, best of 3: 11.2 usec Py2.7: 100000 loops, best of 3: 4.85 usec 3) PyErr_Format(PyExc_TypeError, "[message %s template]", "Abc1") Py3.3: 10000 loops, best of 3: 37.3 usec Py2.7: 10000 loops, best of 3: 25.3 usec Observations: these are really tiny numbers for 100 exceptions. The string formatting case is only some 0.3 microseconds (25x) slower per exception than the constant pointer case, and about 0.2 microseconds (4-5x) slower than the C string constant case. Note that this only benchmarks the exception setting, not the catching, i.e. without the instantiation of the exception object etc., which is identical for all three cases. This change would only apply to Cython generated exceptions (from None safety checks, unbound locals, etc.), which can appear in a lot of places in the C code but should not normally be triggered in production code. If they occur, we'd loose about 0.2 microseconds per exception, comparing 2) and 3). I think that's totally negligible, given that these exceptions potentially indicate a bug in the user code. "strings" tells me that the C compiler really only keeps one copy of the string constants. The savings per exception message are somewhere between 30 and 40 bytes. Not much in today's categories. Assuming even 1000 such exceptions in a large module, that's only some 30K of savings, whereas such a module would likely have a total stripped size of a *lot* more than 1MB. Personally, I think that the performance degradation is basically non-existent, so the space savings come almost for free, however tiny they may be. Stefan From vitja.makarov at gmail.com Sat May 28 11:48:37 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sat, 28 May 2011 13:48:37 +0400 Subject: [Cython] Control Flow In-Reply-To: References: Message-ID: 2011/5/28 Robert Bradshaw : > On Fri, May 27, 2011 at 7:27 AM, Vitja Makarov wrote: >> I've recently fixed some issues: >> >> ?- closure variables were not tracked >> ?- scoped expression variables were initialized to None >> >> So, I should fix broken tests, here are some of them: >> >> nogil (should be fixed) >> purecdef (upstream) >> cfunc_directive_in_pyclass (upstream) >> bufaccess_noassignT444 (should be removed?) >> bufaccess (should be fixed) >> ass2longlong (should be fixed) >> builtinfuncs (should be fixed) >> extcmethcall (should be fixed) >> extcoerce (fixed or removed?) > > Unless you see this code being exercised elsewhere (a run test would > be better her anyways) it's an easy fix that should be done. > >> e_extweakref (should be fixed) >> I've fixed all the tests. Now I see this strange error in py2.4: https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py24-c/lastCompletedBuild/testReport/(root)/CythonCompileTestCase/compiling__c__w_uninitialized_py3/ ***************** compiling (c) w_uninitialized_py3 === Expected errors: === 7:11: local variable 'i' referenced before assignment 13:11: local variable 'i' referenced before assignment === Got errors: === 7:9: undeclared name not builtin: print 7:11: local variable 'i' referenced before assignment 13:11: local variable 'i' referenced before assignment -- vitja. From stefan_ml at behnel.de Sat May 28 13:27:39 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 13:27:39 +0200 Subject: [Cython] Control Flow In-Reply-To: References: Message-ID: <4DE0DC2B.4090905@behnel.de> Vitja Makarov, 28.05.2011 11:48: > 2011/5/28 Robert Bradshaw: >> On Fri, May 27, 2011 at 7:27 AM, Vitja Makarov wrote: >>> I've recently fixed some issues: >>> >>> - closure variables were not tracked >>> - scoped expression variables were initialized to None >>> >>> So, I should fix broken tests, here are some of them: >>> >>> nogil (should be fixed) >>> purecdef (upstream) >>> cfunc_directive_in_pyclass (upstream) >>> bufaccess_noassignT444 (should be removed?) >>> bufaccess (should be fixed) >>> ass2longlong (should be fixed) >>> builtinfuncs (should be fixed) >>> extcmethcall (should be fixed) >>> extcoerce (fixed or removed?) >> >> Unless you see this code being exercised elsewhere (a run test would >> be better her anyways) it's an easy fix that should be done. >> >>> e_extweakref (should be fixed) >>> > > I've fixed all the tests. Cool. > Now I see this strange error in py2.4: > > https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py24-c/lastCompletedBuild/testReport/(root)/CythonCompileTestCase/compiling__c__w_uninitialized_py3/ > > ***************** > compiling (c) w_uninitialized_py3 > === Expected errors: === > 7:11: local variable 'i' referenced before assignment > 13:11: local variable 'i' referenced before assignment > > > === Got errors: === > 7:9: undeclared name not builtin: print > 7:11: local variable 'i' referenced before assignment > 13:11: local variable 'i' referenced before assignment I guess that's http://trac.cython.org/cython_trac/ticket/69 In short, print() still isn't supported before Py2.6. I'd just disable that test in older Python versions for now. Stefan From vitja.makarov at gmail.com Sat May 28 13:48:11 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sat, 28 May 2011 15:48:11 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE0DC2B.4090905@behnel.de> References: <4DE0DC2B.4090905@behnel.de> Message-ID: 2011/5/28 Stefan Behnel : > Vitja Makarov, 28.05.2011 11:48: >> >> 2011/5/28 Robert Bradshaw: >>> >>> On Fri, May 27, 2011 at 7:27 AM, Vitja Makarov wrote: >>>> >>>> I've recently fixed some issues: >>>> >>>> ?- closure variables were not tracked >>>> ?- scoped expression variables were initialized to None >>>> >>>> So, I should fix broken tests, here are some of them: >>>> >>>> nogil (should be fixed) >>>> purecdef (upstream) >>>> cfunc_directive_in_pyclass (upstream) >>>> bufaccess_noassignT444 (should be removed?) >>>> bufaccess (should be fixed) >>>> ass2longlong (should be fixed) >>>> builtinfuncs (should be fixed) >>>> extcmethcall (should be fixed) >>>> extcoerce (fixed or removed?) >>> >>> Unless you see this code being exercised elsewhere (a run test would >>> be better her anyways) it's an easy fix that should be done. >>> >>>> e_extweakref (should be fixed) >>>> >> >> I've fixed all the tests. > > Cool. > > >> Now I see this strange error in py2.4: >> >> >> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py24-c/lastCompletedBuild/testReport/(root)/CythonCompileTestCase/compiling__c__w_uninitialized_py3/ >> >> ***************** >> compiling (c) w_uninitialized_py3 >> === Expected errors: === >> 7:11: local variable 'i' referenced before assignment >> 13:11: local variable 'i' referenced before assignment >> >> >> === Got errors: === >> 7:9: undeclared name not builtin: print >> 7:11: local variable 'i' referenced before assignment >> 13:11: local variable 'i' referenced before assignment > > I guess that's > > http://trac.cython.org/cython_trac/ticket/69 > > In short, print() still isn't supported before Py2.6. I'd just disable that > test in older Python versions for now. > I've replaced print() with dummy ref(obj) function -- vitja. From stefan_ml at behnel.de Sat May 28 13:50:43 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 13:50:43 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> Message-ID: <4DE0E193.3060309@behnel.de> Vitja Makarov, 28.05.2011 13:48: > 2011/5/28 Stefan Behnel: >> Vitja Makarov, 28.05.2011 11:48: >>> >>> 2011/5/28 Robert Bradshaw: >>>> >>>> On Fri, May 27, 2011 at 7:27 AM, Vitja Makarov wrote: >>>>> >>>>> I've recently fixed some issues: >>>>> >>>>> - closure variables were not tracked >>>>> - scoped expression variables were initialized to None >>>>> >>>>> So, I should fix broken tests, here are some of them: >>>>> >>>>> nogil (should be fixed) >>>>> purecdef (upstream) >>>>> cfunc_directive_in_pyclass (upstream) >>>>> bufaccess_noassignT444 (should be removed?) >>>>> bufaccess (should be fixed) >>>>> ass2longlong (should be fixed) >>>>> builtinfuncs (should be fixed) >>>>> extcmethcall (should be fixed) >>>>> extcoerce (fixed or removed?) >>>> >>>> Unless you see this code being exercised elsewhere (a run test would >>>> be better her anyways) it's an easy fix that should be done. >>>> >>>>> e_extweakref (should be fixed) >>>>> >>> >>> I've fixed all the tests. >> >> Cool. >> >> >>> Now I see this strange error in py2.4: >>> >>> >>> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py24-c/lastCompletedBuild/testReport/(root)/CythonCompileTestCase/compiling__c__w_uninitialized_py3/ >>> >>> ***************** >>> compiling (c) w_uninitialized_py3 >>> === Expected errors: === >>> 7:11: local variable 'i' referenced before assignment >>> 13:11: local variable 'i' referenced before assignment >>> >>> >>> === Got errors: === >>> 7:9: undeclared name not builtin: print >>> 7:11: local variable 'i' referenced before assignment >>> 13:11: local variable 'i' referenced before assignment >> >> I guess that's >> >> http://trac.cython.org/cython_trac/ticket/69 >> >> In short, print() still isn't supported before Py2.6. I'd just disable that >> test in older Python versions for now. >> > > I've replaced print() with dummy ref(obj) function Ok, I think we're done then, right? Anything else to do before merging it back? Stefan From vitja.makarov at gmail.com Sat May 28 14:12:59 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sat, 28 May 2011 16:12:59 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE0E193.3060309@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> Message-ID: 2011/5/28 Stefan Behnel : > Vitja Makarov, 28.05.2011 13:48: >> >> 2011/5/28 Stefan Behnel: >>> >>> Vitja Makarov, 28.05.2011 11:48: >>>> >>>> 2011/5/28 Robert Bradshaw: >>>>> >>>>> On Fri, May 27, 2011 at 7:27 AM, Vitja Makarov wrote: >>>>>> >>>>>> I've recently fixed some issues: >>>>>> >>>>>> ?- closure variables were not tracked >>>>>> ?- scoped expression variables were initialized to None >>>>>> >>>>>> So, I should fix broken tests, here are some of them: >>>>>> >>>>>> nogil (should be fixed) >>>>>> purecdef (upstream) >>>>>> cfunc_directive_in_pyclass (upstream) >>>>>> bufaccess_noassignT444 (should be removed?) >>>>>> bufaccess (should be fixed) >>>>>> ass2longlong (should be fixed) >>>>>> builtinfuncs (should be fixed) >>>>>> extcmethcall (should be fixed) >>>>>> extcoerce (fixed or removed?) >>>>> >>>>> Unless you see this code being exercised elsewhere (a run test would >>>>> be better her anyways) it's an easy fix that should be done. >>>>> >>>>>> e_extweakref (should be fixed) >>>>>> >>>> >>>> I've fixed all the tests. >>> >>> Cool. >>> >>> >>>> Now I see this strange error in py2.4: >>>> >>>> >>>> >>>> https://sage.math.washington.edu:8091/hudson/view/cython-vitek/job/cython-vitek-tests-py24-c/lastCompletedBuild/testReport/(root)/CythonCompileTestCase/compiling__c__w_uninitialized_py3/ >>>> >>>> ***************** >>>> compiling (c) w_uninitialized_py3 >>>> === Expected errors: === >>>> 7:11: local variable 'i' referenced before assignment >>>> 13:11: local variable 'i' referenced before assignment >>>> >>>> >>>> === Got errors: === >>>> 7:9: undeclared name not builtin: print >>>> 7:11: local variable 'i' referenced before assignment >>>> 13:11: local variable 'i' referenced before assignment >>> >>> I guess that's >>> >>> http://trac.cython.org/cython_trac/ticket/69 >>> >>> In short, print() still isn't supported before Py2.6. I'd just disable >>> that >>> test in older Python versions for now. >>> >> >> I've replaced print() with dummy ref(obj) function > > Ok, I think we're done then, right? Anything else to do before merging it > back? > I hope so ;) -- vitja. From stefan_ml at behnel.de Sat May 28 16:14:56 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 16:14:56 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> Message-ID: <4DE10360.6000604@behnel.de> Vitja Makarov, 28.05.2011 14:12: > 2011/5/28 Stefan Behnel: >> Ok, I think we're done then, right? Anything else to do before merging it >> back? > > I hope so ;) I gave your branch a test with lxml and it spit out a couple of missing initialisation warnings. Most of them were due to the usage of C out arguments, e.g. cdef Py_ssize_t step ... _PyEval_SliceIndex(sliceobject.step, &step) Here, it doesn't matter that "step" isn't initialised. I guess it's still ok to get a warning, since it's not obvious that "step" will always be set by the function call. Similarly: cdef void _receiveXSLTError(void* c_log_handler, char* msg, ...) nogil: cdef cstd.va_list args ... cstd.va_start(args, msg) Cython now tells me that "args" isn't initialised. That's true again, although this is an even more special case here. I guess I'll have to live with that as well for now, maybe until there's dedicated va_list support in Cython. Next, I got a crash in a part of code where I was manually releasing the GIL, but only conditionally, and Cython figured out that a variable wasn't initialised in one case and injected an exception. I would have liked to get a compile time warning here, but didn't. I assume that's because it was only a "may be used uninitialised", not a "is used uninitialised"? I'm currently looking through the other issues. A major problem is that I often relied on Cython setting uninitialised variables to None, especially in performance critical code where I wanted to avoid double initialisations. Cython is smarter now, so this needs fixing in the code. I'm sure I'm not the only one who'll run into that, so more warnings would be very helpful. Stefan From vitja.makarov at gmail.com Sat May 28 16:58:21 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sat, 28 May 2011 18:58:21 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE10360.6000604@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> Message-ID: 2011/5/28 Stefan Behnel : > Vitja Makarov, 28.05.2011 14:12: >> >> 2011/5/28 Stefan Behnel: >>> >>> Ok, I think we're done then, right? Anything else to do before merging it >>> back? >> >> I hope so ;) > > I gave your branch a test with lxml and it spit out a couple of missing > initialisation warnings. Most of them were due to the usage of C out > arguments, e.g. > > ? ?cdef Py_ssize_t step > ? ?... > ? ?_PyEval_SliceIndex(sliceobject.step, &step) > > Here, it doesn't matter that "step" isn't initialised. I guess it's still ok > to get a warning, since it's not obvious that "step" will always be set by > the function call. > > Similarly: > > ? ?cdef void _receiveXSLTError(void* c_log_handler, char* msg, ...) nogil: > ? ? ? ?cdef cstd.va_list args > ? ? ? ?... > ? ? ? ?cstd.va_start(args, msg) > > Cython now tells me that "args" isn't initialised. That's true again, > although this is an even more special case here. I guess I'll have to live > with that as well for now, maybe until there's dedicated va_list support in > Cython. > > Next, I got a crash in a part of code where I was manually releasing the > GIL, but only conditionally, and Cython figured out that a variable wasn't > initialised in one case and injected an exception. I would have liked to get > a compile time warning here, but didn't. I assume that's because it was only > a "may be used uninitialised", not a "is used uninitialised"? > > I'm currently looking through the other issues. A major problem is that I > often relied on Cython setting uninitialised variables to None, especially > in performance critical code where I wanted to avoid double initialisations. > Cython is smarter now, so this needs fixing in the code. I'm sure I'm not > the only one who'll run into that, so more warnings would be very helpful. > Do you run cython as "cython -Wextra"? -Wextra enables "maybe uninitialized" warning and unused entry. By default error is generated for uninitialized pyobject variables and warning for ctypes. -- vitja. From stefan_ml at behnel.de Sat May 28 17:36:11 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 17:36:11 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> Message-ID: <4DE1166B.50505@behnel.de> Vitja Makarov, 28.05.2011 16:58: > 2011/5/28 Stefan Behnel: >> Vitja Makarov, 28.05.2011 14:12: >>> >>> 2011/5/28 Stefan Behnel: >>>> >>>> Ok, I think we're done then, right? Anything else to do before merging it >>>> back? >>> >>> I hope so ;) >> >> I gave your branch a test with lxml and it spit out a couple of missing >> initialisation warnings. Most of them were due to the usage of C out >> arguments, e.g. >> >> cdef Py_ssize_t step >> ... >> _PyEval_SliceIndex(sliceobject.step,&step) >> >> Here, it doesn't matter that "step" isn't initialised. I guess it's still ok >> to get a warning, since it's not obvious that "step" will always be set by >> the function call. >> >> Similarly: >> >> cdef void _receiveXSLTError(void* c_log_handler, char* msg, ...) nogil: >> cdef cstd.va_list args >> ... >> cstd.va_start(args, msg) >> >> Cython now tells me that "args" isn't initialised. That's true again, >> although this is an even more special case here. I guess I'll have to live >> with that as well for now, maybe until there's dedicated va_list support in >> Cython. >> >> Next, I got a crash in a part of code where I was manually releasing the >> GIL, but only conditionally, and Cython figured out that a variable wasn't >> initialised in one case and injected an exception. I would have liked to get >> a compile time warning here, but didn't. I assume that's because it was only >> a "may be used uninitialised", not a "is used uninitialised"? >> >> I'm currently looking through the other issues. A major problem is that I >> often relied on Cython setting uninitialised variables to None, especially >> in performance critical code where I wanted to avoid double initialisations. >> Cython is smarter now, so this needs fixing in the code. I'm sure I'm not >> the only one who'll run into that, so more warnings would be very helpful. > > Do you run cython as "cython -Wextra"? > -Wextra enables "maybe uninitialized" warning and unused entry. > By default error is generated for uninitialized pyobject variables and > warning for ctypes. No, I was setting the warning level to 0. That should give me all warnings and that, IMHO, includes this one. Stefan From stefan_ml at behnel.de Sat May 28 17:42:41 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 17:42:41 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> Message-ID: <4DE117F1.7090600@behnel.de> Vitja Makarov, 28.05.2011 16:58: > -Wextra enables "maybe uninitialized" warning and unused entry. Interesting: cdef int _raise_if_stored(self) except -1: if self._exc_info is None: return 0 type, value, traceback = self._exc_info self._exc_info = None if value is None and traceback is None: raise type else: raise type, value, traceback src/lxml/lxml.etree.pyx:277:12: Unused entry 'type' I guess that's just a missing marker in RaiseStatNode. Stefan From stefan_ml at behnel.de Sat May 28 18:06:59 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 18:06:59 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> Message-ID: <4DE11DA3.80508@behnel.de> Vitja, here are some more quirks, but they are minor issues. I'll commit my changes to lxml to keep it working, and then merge in the branch. It's certainly in a "good enough for a merge" state. I'm actually surprised how few problems I had to fix, given how old the code in lxml is by now. Let's see how much of Sage we break. Stefan Some more issues: cdef Py_ssize_t c = 0, i [...] while c_node is not NULL and c < count: for i from 0 <= i < step: c_next = next_element(c_next) _removeNode(doc, c_node) c = c + 1 c_node = c_next return 0 src/lxml/apihelpers.pxi:1079:23: Unused entry 'i' (Although the best fix is to change the code to for-in-range() here...) Here's another interesting constellation: live_refs = _convert_xslt_parameters(transform_ctxt, kw, ¶ms) c_result = self._run_transform( c_doc, params, context, transform_ctxt) if params is not NULL: # deallocate space for parameters python.PyMem_Free(params) live_refs = None # release objects src/lxml/xslt.pxi:519:22: Unused entry 'live_refs' So, holding on to Python references to keep their C char* alive gives me a warning. Fine. I guess I'll have to live with that... Another missing bit: cdef void registerExsltFunctions(self): cdef xpath.xmlXPathContext* ctxt = self._xpathCtxt cdef int i cdef char* c_href if xslt.LIBXSLT_VERSION < 10125: # we'd only execute dummy functions anyway return tree.xmlHashScan( self._xpathCtxt.nsHash, _registerExsltFunctionsForNamespaces, self._xpathCtxt) src/lxml/xpath.pxi:80:34: Unused entry 'ctxt' Ok, right, "ctxt" is unused here. But all *3* declarations are actually left-over code from the last refactoring. None of them is used, and I only get one warning? From robertwb at math.washington.edu Sat May 28 18:14:04 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Sat, 28 May 2011 09:14:04 -0700 Subject: [Cython] Redundant Cython exception message strings In-Reply-To: References: <4DE0268E.8040401@behnel.de> Message-ID: On Sat, May 28, 2011 at 1:15 AM, Vitja Makarov wrote: > 2011/5/28 Robert Bradshaw : >> On Fri, May 27, 2011 at 3:32 PM, Stefan Behnel wrote: >>> Hi, >>> >>> I recently stumbled over a tradeoff question with AttributeError, and now >>> found the same situation for UnboundLocalError in Vitja's control flow >>> branch. So here it is. >>> >>> When we raise an exception several times in different parts of the code with >>> a message that only differs slightly each time (usually something like >>> "'NoneType' has no attribute X", or "local variable X referenced before >>> assignment"), we have three choices to handle this: >>> >>> 1) Optimise for speed: create a Python string object at module >>> initialisation time and call PyErr_SetObject(exc_type, msg_str_obj). >>> >>> 2) Current way: let CPython create the string object when raising the >>> exception and just call PyErr_SetString(exc_type, "complete message"). >>> >>> 3) Trade speed for size and allow the C compiler to reduce the storage >>> redundancy: write only the message template and the names as C char* >>> constants by calling PyErr_Format(exc_type, "message template %s", "X"). >>> >>> Assuming that exceptions should be exceptional, I'm leaning towards 3). This >>> would allow the C compiler to collapse multiple usages of the same C string >>> into one data constant, thus reducing a bit of redundancy in the shared >>> library size and the memory footprint. However, it would (slightly?) slow >>> down the exception raising due to the additional string formatting, even >>> when compared to the need to build a Python string object that it shares >>> with 2). While 1) would obviously be the fastest way to raise an exception >>> (no memory allocation, only refcounting), I think it's not worth it for >>> exceptions as it increases both the runtime memory overhead and the module >>> startup time. >>> >>> Thoughts? >> >> Any back-of-the-envelope calculations on how much the savings would >> be? I think I'm leaning towards 3 as well, certainly not option 1. >> > > For UnboundLocalError and NameError I used 2) way: > > https://github.com/vitek/cython/commit/1fe86b85d965753244cd09db38b1089b40f09a58 > > So maybe I should add functions like __Pyx_RaiseUnboundLocalError and > __Pyx_RaiseClosureNameError that will ?use 3) way. > How do you like put_error_if_unbound CCodeWriter method is that right > place for it? I don't think abstracting it out to a function really saves anything here given that Python already has PyErr_Format. - Robert From robertwb at math.washington.edu Sat May 28 18:15:26 2011 From: robertwb at math.washington.edu (Robert Bradshaw) Date: Sat, 28 May 2011 09:15:26 -0700 Subject: [Cython] Redundant Cython exception message strings In-Reply-To: <4DE0C253.2020000@behnel.de> References: <4DE0268E.8040401@behnel.de> <4DE0C253.2020000@behnel.de> Message-ID: On Sat, May 28, 2011 at 2:37 AM, Stefan Behnel wrote: > Robert Bradshaw, 28.05.2011 00:39: >> >> On Fri, May 27, 2011 at 3:32 PM, Stefan Behnel wrote: >>> >>> I recently stumbled over a tradeoff question with AttributeError, and now >>> found the same situation for UnboundLocalError in Vitja's control flow >>> branch. So here it is. >>> >>> When we raise an exception several times in different parts of the code >>> with >>> a message that only differs slightly each time (usually something like >>> "'NoneType' has no attribute X", or "local variable X referenced before >>> assignment"), we have three choices to handle this: >>> >>> 1) Optimise for speed: create a Python string object at module >>> initialisation time and call PyErr_SetObject(exc_type, msg_str_obj). >>> >>> 2) Current way: let CPython create the string object when raising the >>> exception and just call PyErr_SetString(exc_type, "complete message"). >>> >>> 3) Trade speed for size and allow the C compiler to reduce the storage >>> redundancy: write only the message template and the names as C char* >>> constants by calling PyErr_Format(exc_type, "message template %s", "X"). >>> >>> Assuming that exceptions should be exceptional, I'm leaning towards 3). >>> This >>> would allow the C compiler to collapse multiple usages of the same C >>> string >>> into one data constant, thus reducing a bit of redundancy in the shared >>> library size and the memory footprint. However, it would (slightly?) slow >>> down the exception raising due to the additional string formatting, even >>> when compared to the need to build a Python string object that it shares >>> with 2). While 1) would obviously be the fastest way to raise an >>> exception >>> (no memory allocation, only refcounting), I think it's not worth it for >>> exceptions as it increases both the runtime memory overhead and the >>> module >>> startup time. >> >> Any back-of-the-envelope calculations on how much the savings would >> be? > > As a micro benchmark, I wrote three C functions that do 10 exception setting > calls and then clear the exception, and called those 10x in a loop (i.e. 100 > exceptions). Results: > > 1) PyErr_SetObject(PyExc_TypeError, Py_None) > Py3.3: 1000000 loops, best of 3: 1.42 usec > Py2.7: 1000000 loops, best of 3: 0.965 usec > > 2) PyErr_SetString(PyExc_TypeError, "[complete message]") > Py3.3: 100000 loops, best of 3: 11.2 usec > Py2.7: 100000 loops, best of 3: 4.85 usec > > 3) PyErr_Format(PyExc_TypeError, "[message %s template]", "Abc1") > Py3.3: 10000 loops, best of 3: 37.3 usec > Py2.7: 10000 loops, best of 3: 25.3 usec > > Observations: these are really tiny numbers for 100 exceptions. The string > formatting case is only some 0.3 microseconds (25x) slower per exception > than the constant pointer case, and about 0.2 microseconds (4-5x) slower > than the C string constant case. > > Note that this only benchmarks the exception setting, not the catching, i.e. > without the instantiation of the exception object etc., which is identical > for all three cases. > > This change would only apply to Cython generated exceptions (from None > safety checks, unbound locals, etc.), which can appear in a lot of places in > the C code but should not normally be triggered in production code. If they > occur, we'd loose about 0.2 microseconds per exception, comparing 2) and 3). > I think that's totally negligible, given that these exceptions potentially > indicate a bug in the user code. > > "strings" tells me that the C compiler really only keeps one copy of the > string constants. The savings per exception message are somewhere between 30 > and 40 bytes. Not much in today's categories. Assuming even 1000 such > exceptions in a large module, that's only some 30K of savings, whereas such > a module would likely have a total stripped size of a *lot* more than 1MB. > > Personally, I think that the performance degradation is basically > non-existent, so the space savings come almost for free, however tiny they > may be. Sounds good. I'm fine with 2 or 3, and despite the performance advantage of 1, it should be the exceptional case to raise this kind of error, and the module initialization time is and issue. - Robert From stefan_ml at behnel.de Sat May 28 18:21:37 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 18:21:37 +0200 Subject: [Cython] Redundant Cython exception message strings In-Reply-To: References: <4DE0268E.8040401@behnel.de> Message-ID: <4DE12111.3080308@behnel.de> Robert Bradshaw, 28.05.2011 18:14: > On Sat, May 28, 2011 at 1:15 AM, Vitja Makarov wrote: >> So maybe I should add functions like __Pyx_RaiseUnboundLocalError and >> __Pyx_RaiseClosureNameError that will use 3) way. >> How do you like put_error_if_unbound CCodeWriter method is that right >> place for it? > > I don't think abstracting it out to a function really saves anything > here given that Python already has PyErr_Format. Agreed. The existing functions are only there because they are used in multiple places, and usually receive formatting arguments. So putting them into one function makes it easier to keep the message consistent etc. I also checked that even if you only call PyErr_Format() with multiple constant string arguments, without going through a function that explicitly declares them "const char*", gcc considers them "const char*" automatically and reuses the same constant in different places. Stefan From stefan_ml at behnel.de Sat May 28 20:59:19 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sat, 28 May 2011 20:59:19 +0200 Subject: [Cython] Control Flow In-Reply-To: <4DE11DA3.80508@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> Message-ID: <4DE14607.50409@behnel.de> Stefan Behnel, 28.05.2011 18:06: > Let's see how much of Sage we break. ... quite a bit. From a superficial glance, there seem to be some real bugs, but most of the failures and warnings are most likely just uninitialised variables that are expected to be None. https://sage.math.washington.edu:8091/hudson/view/All/job/sage-build/740/consoleFull Stefan From vitja.makarov at gmail.com Sun May 29 10:11:51 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sun, 29 May 2011 12:11:51 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE14607.50409@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> Message-ID: 2011/5/28 Stefan Behnel : > Stefan Behnel, 28.05.2011 18:06: >> >> Let's see how much of Sage we break. > > ... quite a bit. From a superficial glance, there seem to be some real bugs, > but most of the failures and warnings are most likely just uninitialised > variables that are expected to be None. > > https://sage.math.washington.edu:8091/hudson/view/All/job/sage-build/740/consoleFull > I've started new branch called control_flow_fixes. I've fixed the issue with RaiseStatNode. And unused variables that were not assigned or referenced now you get correct message. And I started to look inside sage problems. Error compiling Cython file: ------------------------------------------------------------ ... # allow lambda functions if self._nrows==0 or self._ncols==0: return self.__copy__() v = [z.derivative(var) for z in self.list()] if R is None: ^ ------------------------------------------------------------ sage/matrix/matrix_dense.pyx:451:13: local variable 'R' referenced before assignment I've looked into the sources and I think as cython is right here. 'R' is allways NULL at that point. -- vitja. From stefan_ml at behnel.de Sun May 29 10:19:50 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sun, 29 May 2011 10:19:50 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> Message-ID: <4DE201A6.3010806@behnel.de> Vitja Makarov, 29.05.2011 10:11: > 2011/5/28 Stefan Behnel: >> Stefan Behnel, 28.05.2011 18:06: >>> >>> Let's see how much of Sage we break. >> >> ... quite a bit. From a superficial glance, there seem to be some real bugs, Bugs in Sage, to be clear. >> but most of the failures and warnings are most likely just uninitialised >> variables that are expected to be None. >> >> https://sage.math.washington.edu:8091/hudson/view/All/job/sage-build/740/consoleFull > > > I've started new branch called control_flow_fixes. I think you can safely apply the subsequent fixes to the master branch, now that the feature is in. That will also give you broader feedback from Jenkins. > I've fixed the issue with RaiseStatNode. And unused variables that > were not assigned or referenced now you get correct message. Cool. > And I started to look inside sage problems. > > Error compiling Cython file: > ------------------------------------------------------------ > ... > # allow lambda functions > > if self._nrows==0 or self._ncols==0: > return self.__copy__() > v = [z.derivative(var) for z in self.list()] > if R is None: > ^ > ------------------------------------------------------------ > > sage/matrix/matrix_dense.pyx:451:13: local variable 'R' referenced > before assignment > > I've looked into the sources and I think as cython is right here. 'R' > is allways NULL at that point. Yes, that's one of the things I meant. It looked like a Sage bug right away. Stefan From vitja.makarov at gmail.com Sun May 29 11:17:05 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sun, 29 May 2011 13:17:05 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE201A6.3010806@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> Message-ID: 2011/5/29 Stefan Behnel : > Vitja Makarov, 29.05.2011 10:11: >> >> 2011/5/28 Stefan Behnel: >>> >>> Stefan Behnel, 28.05.2011 18:06: >>>> >>>> Let's see how much of Sage we break. >>> >>> ... quite a bit. From a superficial glance, there seem to be some real >>> bugs, > > Bugs in Sage, to be clear. > Ok. > >>> but most of the failures and warnings are most likely just uninitialised >>> variables that are expected to be None. >>> >>> >>> https://sage.math.washington.edu:8091/hudson/view/All/job/sage-build/740/consoleFull >> >> >> I've started new branch called control_flow_fixes. > > I think you can safely apply the subsequent fixes to the master branch, now > that the feature is in. That will also give you broader feedback from > Jenkins. > > I don't have write access to upstream repo. Btw there is one more commit in control_flow_fixes branch with few new tests. >> I've fixed the issue with RaiseStatNode. And unused variables that >> were not assigned or referenced now you get correct message. > > Cool. > What about "Error running command, failed with status 256." lines in sage build log? Is that cython crash? -- vitja. From stefan_ml at behnel.de Sun May 29 13:28:50 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Sun, 29 May 2011 13:28:50 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> Message-ID: <4DE22DF2.6090305@behnel.de> Vitja Makarov, 29.05.2011 11:17: > 2011/5/29 Stefan Behnel: >> Vitja Makarov, 29.05.2011 10:11: >>> I've started new branch called control_flow_fixes. >> >> I think you can safely apply the subsequent fixes to the master branch, now >> that the feature is in. That will also give you broader feedback from >> Jenkins. > > I don't have write access to upstream repo. Ah, sorry. I added you to the project members. > Btw there is one more commit in control_flow_fixes branch with few new tests. That makes a good test for your write access then. ;) > What about "Error running command, failed with status 256." lines in > sage build log? > Is that cython crash? Don't think so. Not sure what those failures are, but given that some modules fail to compile, maybe it's just the late result of such a build failure. Stefan From vitja.makarov at gmail.com Sun May 29 18:03:24 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Sun, 29 May 2011 20:03:24 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE22DF2.6090305@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> <4DE22DF2.6090305@behnel.de> Message-ID: 2011/5/29 Stefan Behnel : > Vitja Makarov, 29.05.2011 11:17: >> >> 2011/5/29 Stefan Behnel: >>> >>> Vitja Makarov, 29.05.2011 10:11: >>>> >>>> I've started new branch called control_flow_fixes. >>> >>> I think you can safely apply the subsequent fixes to the master branch, >>> now >>> that the feature is in. That will also give you broader feedback from >>> Jenkins. >> >> I don't have write access to upstream repo. > > Ah, sorry. I added you to the project members. > > >> Btw there is one more commit in control_flow_fixes branch with few new >> tests. > > That makes a good test for your write access then. ;) > Thanks. I've successfully pushed my changes. I removed old ControlFlow stuff completely. > >> What about "Error running command, failed with status 256." lines in >> sage build log? >> Is that cython crash? > > Don't think so. Not sure what those failures are, but given that some > modules fail to compile, maybe it's just the late result of such a build > failure. > -- vitja. From vitja.makarov at gmail.com Mon May 30 20:53:20 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Mon, 30 May 2011 22:53:20 +0400 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> <4DE22DF2.6090305@behnel.de> Message-ID: 2011/5/29 Vitja Makarov : > 2011/5/29 Stefan Behnel : >> Vitja Makarov, 29.05.2011 11:17: >>> >>> 2011/5/29 Stefan Behnel: >>>> >>>> Vitja Makarov, 29.05.2011 10:11: >>>>> >>>>> I've started new branch called control_flow_fixes. >>>> >>>> I think you can safely apply the subsequent fixes to the master branch, >>>> now >>>> that the feature is in. That will also give you broader feedback from >>>> Jenkins. >>> >>> I don't have write access to upstream repo. >> >> Ah, sorry. I added you to the project members. >> >> >>> Btw there is one more commit in control_flow_fixes branch with few new >>> tests. >> >> That makes a good test for your write access then. ;) >> > > Thanks. I've successfully pushed my changes. > I removed old ControlFlow stuff completely. > > >> >>> What about "Error running command, failed with status 256." lines in >>> sage build log? >>> Is that cython crash? >> >> Don't think so. Not sure what those failures are, but given that some >> modules fail to compile, maybe it's just the late result of such a build >> failure. >> I see sigsegv in lxml tests: 1222/1364 ( 89.6%): test_xmlschema_import_file (lxml.tests.test_xmlschema.ETreeXMLSchemaTestCase) ... Segmentation fault https://sage.math.washington.edu:8091/hudson/job/cython-devel-lxml-trunk-py27/890/console Is that control flow related issue? -- vitja. From stefan_ml at behnel.de Mon May 30 21:59:11 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 30 May 2011 21:59:11 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> <4DE22DF2.6090305@behnel.de> Message-ID: <4DE3F70F.2050101@behnel.de> Vitja Makarov, 30.05.2011 20:53: > I see sigsegv in lxml tests: > > 1222/1364 ( 89.6%): test_xmlschema_import_file > (lxml.tests.test_xmlschema.ETreeXMLSchemaTestCase) ... Segmentation > fault > https://sage.math.washington.edu:8091/hudson/job/cython-devel-lxml-trunk-py27/890/console > > Is that control flow related issue? No, don't bother with that one. It's been crashing at that point for ages and I can't figure out why. It only crashes on sage.math, and only when running two of the tests in combination (a threading test and the one above). So far, I couldn't reproduce this on any other machine, nor is it any clear what may trigger this. I'm pretty sure it's not a Cython related bug, though. Stefan From vitja.makarov at gmail.com Mon May 30 22:15:56 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Tue, 31 May 2011 00:15:56 +0400 Subject: [Cython] Control Flow In-Reply-To: <4DE3F70F.2050101@behnel.de> References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> <4DE22DF2.6090305@behnel.de> <4DE3F70F.2050101@behnel.de> Message-ID: 2011/5/30 Stefan Behnel : > Vitja Makarov, 30.05.2011 20:53: >> >> I see sigsegv in lxml tests: >> >> 1222/1364 ( 89.6%): test_xmlschema_import_file >> (lxml.tests.test_xmlschema.ETreeXMLSchemaTestCase) ... Segmentation >> fault >> >> https://sage.math.washington.edu:8091/hudson/job/cython-devel-lxml-trunk-py27/890/console >> >> Is that control flow related issue? > > No, don't bother with that one. > > It's been crashing at that point for ages and I can't figure out why. It > only crashes on sage.math, and only when running two of the tests in > combination (a threading test and the one above). So far, I couldn't > reproduce this on any other machine, nor is it any clear what may trigger > this. I'm pretty sure it's not a Cython related bug, though. > Ok, according to last 4 builds it's fails 75% so maybe try to run it under gdb with bt hook? -- vitja. From stefan_ml at behnel.de Mon May 30 22:41:50 2011 From: stefan_ml at behnel.de (Stefan Behnel) Date: Mon, 30 May 2011 22:41:50 +0200 Subject: [Cython] Control Flow In-Reply-To: References: <4DE0DC2B.4090905@behnel.de> <4DE0E193.3060309@behnel.de> <4DE10360.6000604@behnel.de> <4DE11DA3.80508@behnel.de> <4DE14607.50409@behnel.de> <4DE201A6.3010806@behnel.de> <4DE22DF2.6090305@behnel.de> <4DE3F70F.2050101@behnel.de> Message-ID: <4DE4010E.1010506@behnel.de> Vitja Makarov, 30.05.2011 22:15: > 2011/5/30 Stefan Behnel: >> Vitja Makarov, 30.05.2011 20:53: >>> >>> I see sigsegv in lxml tests: >>> >>> 1222/1364 ( 89.6%): test_xmlschema_import_file >>> (lxml.tests.test_xmlschema.ETreeXMLSchemaTestCase) ... Segmentation >>> fault >>> >>> https://sage.math.washington.edu:8091/hudson/job/cython-devel-lxml-trunk-py27/890/console >>> >>> Is that control flow related issue? >> >> No, don't bother with that one. >> >> It's been crashing at that point for ages and I can't figure out why. It >> only crashes on sage.math, and only when running two of the tests in >> combination (a threading test and the one above). So far, I couldn't >> reproduce this on any other machine, nor is it any clear what may trigger >> this. I'm pretty sure it's not a Cython related bug, though. > > Ok, according to last 4 builds it's fails 75% so maybe try to run it > under gdb with bt hook? I *know* where it fails. But that doesn't really tell me *why* it fails. As I said, it only crashes when one of the threading tests runs before it. I can only guess that the thread interaction somehow leaves libxml2 in an inconsistent state, which then triggers a crash later on in the schema test. Stefan From romain.py at gmail.com Mon May 30 23:31:51 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Mon, 30 May 2011 23:31:51 +0200 Subject: [Cython] [GSoC] Blog post regarding the Cython backend aiming PyPy Message-ID: <20110530213151.GA26763@ubuntu> Hi I've posted and article on my blog that explains what I've done during the community bonding period and the first week of the Google Summer of Code : http://rguillebert.blogspot.com/2011/05/cython-backend-aiming-pypy-week-1.html Cheers Romain From romain.py at gmail.com Mon May 30 23:18:20 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Mon, 30 May 2011 23:18:20 +0200 Subject: [Cython] [GSoC] Blog post regarding the Cython backend aiming PyPy Message-ID: <20110530211820.GA25753@ubuntu> Hi I've posted and article on my blog that explains what I've done during the community bonding period and the first week of the Google Summer of Code : http://rguillebert.blogspot.com/2011/05/cython-backend-aiming-pypy-week-1.html Cheers Romain From romain.py at gmail.com Mon May 30 23:41:16 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Mon, 30 May 2011 23:41:16 +0200 Subject: [Cython] [GSoC] Blog post regarding the Cython backend aiming PyPy Message-ID: <20110530214116.GC26763@ubuntu> Hi I've posted and article on my blog that explains what I've done during the community bonding period and the first week of the Google Summer of Code : http://rguillebert.blogspot.com/2011/05/cython-backend-aiming-pypy-week-1.html Cheers Romain From vitja.makarov at gmail.com Tue May 31 07:34:32 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Tue, 31 May 2011 09:34:32 +0400 Subject: [Cython] wiki.cython.org is down Message-ID: With error: Service Temporarily Unavailable The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. -- vitja. From markflorisson88 at gmail.com Tue May 31 12:08:52 2011 From: markflorisson88 at gmail.com (mark florisson) Date: Tue, 31 May 2011 12:08:52 +0200 Subject: [Cython] [GSoC] Blog post regarding the Cython backend aiming PyPy In-Reply-To: <20110530213151.GA26763@ubuntu> References: <20110530213151.GA26763@ubuntu> Message-ID: On 30 May 2011 23:31, Romain Guillebert wrote: > Hi > > I've posted and article on my blog that explains what I've done during > the community bonding period and the first week of the Google Summer of > Code : > http://rguillebert.blogspot.com/2011/05/cython-backend-aiming-pypy-week-1.html > > Cheers > Romain > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > Cool. Would it be useful to always generate wrapper functions for extern functions with numeric argument types? E.g. this is valid Cython code: cdef extern from "foo.h": ctypedef unsigned int size_t size_t func_with_typedef_arg(size_t a) So here the ctypedef for size_t is unsigned int, which is only valid in C for some platforms/architectures. So perhaps a wrapper function could solve that issue: int __pyx_wrapper_func_with_typedef_arg(int a) { /* some bounds and sign checking code here ? */ return func_with_typedef(a); } Because then you always know that calling it with argtypes = [c_int] and restype = c_int is valid. (BTW, it's also valid to declare something as a function which is actually a macro, so I suppose you always need wrappers for functions.) Do you already have an idea how to handle struct type arguments? Those are often also incomplete... but perhaps I'm geting too far ahead, I don't think we're quite there yet. I suppose you could also place this ABI burden on the user (for now), as does ctypes. As for the linking stuff, perhaps it's a good idea to look at http://wiki.cython.org/enhancements/distutils_preprocessing (currently down unfortunately, but in google cache). Then you can list libraries like this: '# distutils: libraries = spam eggs' at the top of the file. Cheers, Mark From vitja.makarov at gmail.com Tue May 31 13:07:49 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Tue, 31 May 2011 15:07:49 +0400 Subject: [Cython] local variable handling in generators In-Reply-To: <4DDB3520.5020609@behnel.de> References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> <4DDAA9DF.2000809@behnel.de> <4DDB3520.5020609@behnel.de> Message-ID: 2011/5/24 Stefan Behnel : > Vitja Makarov, 23.05.2011 21:33: >> >> 2011/5/23 Stefan Behnel: >>> >>> However, once we really know which values change between yield calls, >>> i.e. >>> which ones need to be stored away, it will actually be less expensive in >>> most cases. We currently pay the indirection penalty for each access, >>> even >>> read access, whereas the C compiler can then keep important variables in >>> registers and only write them back once per yield. >>> >> >> I think that all not NULL variables should be saved/restored inside yield. >> I can not really track changes only assignments. > > I mean "assignments" when I write "changes". When a variable is being > assigned to, we should assume that its value changed. Users can be expected > to be smart enough to avoid unnecessary assignments in most cases, there's > no need to put work into optimising them away automatically. > > >> for i in a: >> ? ? yield i ?# j is NULL here >> for j in b: >> ? ? yield j # a, b, i ,j should be saved/restored > > Right. However, in general, we can expect that most variables will have been > initialised on a yield. > > We can still avoid storing away C typed variables that are not being used > later on, because they are not reference counted. > > And if the user sets 'a' and 'i' to None between the loops, they won't need > to be saved on the second yield either. But that's an optimisation, not a > requirement. > What about copying C++ structs and objects with constructor (and/or overloaded = method)? That wouldn't work well. -- vitja. From d.s.seljebotn at astro.uio.no Tue May 31 13:18:41 2011 From: d.s.seljebotn at astro.uio.no (Dag Sverre Seljebotn) Date: Tue, 31 May 2011 13:18:41 +0200 Subject: [Cython] local variable handling in generators In-Reply-To: References: <4DD90292.8070505@behnel.de> <4DDA1AD6.1070309@behnel.de> <4DDA259B.1000203@behnel.de> <4DDA2909.20604@behnel.de> <4DDA2F80.3060907@behnel.de> <4DDAA9DF.2000809@behnel.de> <4DDB3520.5020609@behnel.de> Message-ID: <4DE4CE91.3000009@astro.uio.no> On 05/31/2011 01:07 PM, Vitja Makarov wrote: > 2011/5/24 Stefan Behnel: >> Vitja Makarov, 23.05.2011 21:33: >>> >>> 2011/5/23 Stefan Behnel: >>>> >>>> However, once we really know which values change between yield calls, >>>> i.e. >>>> which ones need to be stored away, it will actually be less expensive in >>>> most cases. We currently pay the indirection penalty for each access, >>>> even >>>> read access, whereas the C compiler can then keep important variables in >>>> registers and only write them back once per yield. >>>> >>> >>> I think that all not NULL variables should be saved/restored inside yield. >>> I can not really track changes only assignments. >> >> I mean "assignments" when I write "changes". When a variable is being >> assigned to, we should assume that its value changed. Users can be expected >> to be smart enough to avoid unnecessary assignments in most cases, there's >> no need to put work into optimising them away automatically. >> >> >>> for i in a: >>> yield i # j is NULL here >>> for j in b: >>> yield j # a, b, i ,j should be saved/restored >> >> Right. However, in general, we can expect that most variables will have been >> initialised on a yield. >> >> We can still avoid storing away C typed variables that are not being used >> later on, because they are not reference counted. >> >> And if the user sets 'a' and 'i' to None between the loops, they won't need >> to be saved on the second yield either. But that's an optimisation, not a >> requirement. >> > > What about copying C++ structs and objects with constructor (and/or > overloaded = method)? > That wouldn't work well. Currently I believe C++ objects are only supported through pointers, which of course are copyable. If or when we support C++ objects on the stack, then we should definitely avoid copying them. If you declare a C++ class as a struct Cython-side then I think we should assume that we can freely invoke the copy constructor and assignment operator in this context. Dag Sverre From wstein at gmail.com Tue May 31 17:02:37 2011 From: wstein at gmail.com (William Stein) Date: Tue, 31 May 2011 08:02:37 -0700 Subject: [Cython] wiki.cython.org is down In-Reply-To: References: Message-ID: Fixed. On Mon, May 30, 2011 at 10:34 PM, Vitja Makarov wrote: > With error: > > Service Temporarily Unavailable > > The server is temporarily unable to service your request due to > maintenance downtime or capacity problems. Please try again later. > > > -- > vitja. > _______________________________________________ > cython-devel mailing list > cython-devel at python.org > http://mail.python.org/mailman/listinfo/cython-devel > -- William Stein Professor of Mathematics University of Washington http://wstein.org From romain.py at gmail.com Tue May 31 17:08:20 2011 From: romain.py at gmail.com (Romain Guillebert) Date: Tue, 31 May 2011 17:08:20 +0200 Subject: [Cython] [GSoC] Blog post regarding the Cython backend aiming PyPy In-Reply-To: References: <20110530213151.GA26763@ubuntu> Message-ID: <20110531150820.GA31833@ubuntu> On Tue, May 31, 2011 at 12:08:52PM +0200, mark florisson wrote: > Cool. Would it be useful to always generate wrapper functions for > extern functions with numeric argument types? E.g. this is valid > Cython code: > > cdef extern from "foo.h": > ctypedef unsigned int size_t > size_t func_with_typedef_arg(size_t a) > > So here the ctypedef for size_t is unsigned int, which is only valid > in C for some platforms/architectures. So perhaps a wrapper function > could solve that issue: > > int __pyx_wrapper_func_with_typedef_arg(int a) { > /* some bounds and sign checking code here ? */ > return func_with_typedef(a); > } > > Because then you always know that calling it with argtypes = [c_int] > and restype = c_int is valid. > (BTW, it's also valid to declare something as a function which is > actually a macro, so I suppose you always need wrappers for > functions.) > > Do you already have an idea how to handle struct type arguments? Those > are often also incomplete... but perhaps I'm geting too far ahead, I > don't think we're quite there yet. I suppose you could also place this > ABI burden on the user (for now), as does ctypes. > > As for the linking stuff, perhaps it's a good idea to look at > http://wiki.cython.org/enhancements/distutils_preprocessing (currently > down unfortunately, but in google cache). Then you can list libraries > like this: '# distutils: libraries = spam eggs' at the top of the > file. > > Cheers, > > Mark Hi Mark For the moment, I try to handle the standard case : call a function with C basic types, then add structures and pass by pointer. To deal with the ABI, fijal told me that there's a tool called ctypes_configure, I will investigate this to see what I can get from it. Cheers Romain From vitja.makarov at gmail.com Tue May 31 20:25:44 2011 From: vitja.makarov at gmail.com (Vitja Makarov) Date: Tue, 31 May 2011 22:25:44 +0400 Subject: [Cython] Bindings performance issue Message-ID: Hi! Is bindings performance issue valuable? $ cat bindbench.pyx def wo_bindings(): pass def outer(): def inner(): pass return inner with_bindings = outer() $ python >>> import timeit >>> timeit.repeat('with_bindings()', setup='from bindbench import wo_bindings, with_bindings', repeat=1, number=100000000) [6.169871807098389] >>> timeit.repeat('wo_bindings()', setup='from bindbench import wo_bindings, with_bindings', repeat=1, number=100000000) [4.609416961669922] PyCBindings makes it 1.3 (difference is about 15ns on my laptop) times slower for CPython interpreter execution. As CPython has some optimizations for CFunctions and PyCFunctions. Does it make sense for us? Or we can easily switch to bindings? -- vitja.