[Cython] Code generated for the expression int(x)+1

2012-05-01 Thread Ask F. Jakobsen
Hi all,

I am having a simple performance problem that can be resolved by splitting up 
an expression in two lines. I don't know if it is a bug or I am missing 
something.

The piece of code below is translated to slow code

1)
cdef int i
i=int(x)+1

whereas the code below is translated to fast code

2)
cdef int i
i=int(x)
i=i+1

Snippet of generated code by cython

1)


  /* "test.pyx":4
 * cdef double x=3.2
 * cdef int i
 * i=int(x)+1 # <<
 * return i
 * 
 */
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_x); if (unlikely(!__pyx_t_1)) 
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto 
__pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = 
__pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyInt_Type))), 
((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = 
__pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
  __pyx_t_2 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_2)) 
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto 
__pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) 
&& PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; 
__pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_i = __pyx_t_3;

2)

  /* "test.pyx":11
 * cdef double x=3.2
 * cdef int i
 * i=int(x) # <<
 * i=i+1
 * return i
 */
  __pyx_v_i = ((int)__pyx_v_x);

  /* "test.pyx":12
 * cdef int i
 * i=int(x)
 * i=i+1 # <<
 * return i
 * 
 */
  __pyx_v_i = (__pyx_v_i + 1);


I am using Cython-0.15.1

Best regards,
  Ask
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Code generated for the expression int(x)+1

2012-05-01 Thread Stefan Behnel
Ask F. Jakobsen, 01.05.2012 09:53:
> I am having a simple performance problem that can be resolved by splitting up 
> an expression in two lines. I don't know if it is a bug or I am missing 
> something.
> 
> The piece of code below is translated to slow code
> 
> 1)
> cdef int i
> i=int(x)+1

What you are saying here is:

Convert x (known to be a C double) to an arbitrary size Python integer
value, add 1, convert it to a C int and assign it to i.


> whereas the code below is translated to fast code
> 
> 2)
> cdef int i
> i=int(x)
> i=i+1

This means:

Convert x (known to be a C double) to an arbitrary size Python integer
value, convert that to a C int and assign it to i, then add 1 and assign
the result to i.

In the first case, Cython cannot safely assume that the result of the int()
conversion will fit into a C int and will therefore evaluate the expression
in Python space. Note that the "+1" only hits a specific case where it
looks safe, if you had written "int(x) // 200", this decision would make a
lot more sense, because the intermediate result of int(x) could really be
larger than a C int, even though the result of the division will have to
fit into one (or will be made to fit, because you say so).

In the second case, you explicitly tell Cython that the result of the int()
conversion will fit into a C int and that *you* accept the responsibility
for any overflows, so Cython can safely optimise the Python coercion away
and reduce the int() call to a bare C cast from double to int.

You can get the same result by writing down the cast yourself.

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Wacky idea: proper macros

2012-05-01 Thread Dag Sverre Seljebotn

On 04/30/2012 11:36 PM, William Stein wrote:

On Mon, Apr 30, 2012 at 2:32 PM, Dag Sverre Seljebotn
  wrote:



Wes McKinney  wrote:


On Mon, Apr 30, 2012 at 4:55 PM, Nathaniel Smith  wrote:

On Mon, Apr 30, 2012 at 9:49 PM, Dag Sverre Seljebotn
  wrote:

JIT is really the way to go. It is one thing that a JIT could

optimize the

case where you pass a callback to a function and inline it run-time.

But

even if it doesn't get that fancy, it'd be great to just be able to

write

something like "cython.eval(s)" and have that be compiled (I guess

you could

do that now, but the sheer overhead of the C compiler and all the

.so files

involved means nobody would sanely use that as the main way of

stringing

together something like pandas).


The overhead of running a fully optimizing compiler over pandas on
every import is pretty high, though. You can come up with various
caching mechanisms, but they all mean introducing some kind of

compile

time/run time distinction. So I'm skeptical we'll just be able to get
rid of that concept, even in a brave new LLVM/PyPy/Julia world.

-- Nathaniel
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


I'd be perfectly OK with just having to compile pandas's "data engine"
and generate loads of C/C++ code. JIT-compiling little array
expressions would be cool too. I've got enough of an itch that I might
have to start scratching pretty soon.


I think a good start is:

Myself I'd look into just using Jinja2 to generate all the Cython code, rather 
than those horrible Python interpolated strings...that should give you 
something that's at least rather pleasant for you to work with once you are 
used to it (even if it is a bit horrible to newcomers to the code base).

You can even check in the generated sources.

And we've discussed letting cython be smart with templating languages and error 
report on a line in the original template, such features will certainly 
accepted once somebody codes it up.

  (I can give you me breakdown of how I eliminate other templating languages 
than Jinja2 for this purpose tomorrow if you are interested).


Can you point us to a good example of you using jinja2 for this purpose?


Sure, I just needed some sleep...

I only use it for C code, haven't used it for Cython so far (I tend to 
write things in C and wrap it in Cython).


1)

https://github.com/dagss/elemental4py/blob/master/src/elemental_wrapper.cpp.in

(work-in-progress) Here I use Jinja2 to write a C wrapper around 
Elemental (Elemental is a library for dense linear algebra over MPI). 
The C++ library is a heavy user of templates, I replace the templates 
with run-time dispatches using if-tests, so that rather than 
"DistMatrix" you have an elem_matrix struct with 
ELEM_DOUBLE, ELEM_MC, ELEM_MR.


2)

https://github.com/wavemoth/wavemoth/blob/master/src/legendre_transform.c.in

This is a numerical kernel where I do loop unrolling etc. using 
metaprogramming (with Tempita, not Jinja2).


https://github.com/wavemoth/wavemoth/blob/cuda/wavemoth/cuda/legendre_transform.cu.in

3)

https://github.com/wavemoth/wavemoth/blob/cuda/wavemoth/cuda/legendre_transform.cu.in

Numerical kernel in templated CUDA using Tempita.

On templating languages I tried)

I've scanned through a few and actually tried Tempita, Mako, Jinja2.

The features I need:

 - Pythonic syntax and ability to embed arbitrary Python code

 - A "call-block", such as this

  {% call catch('A->grid->ctx') %}
  BODY
  {% endcall %}


i.e. in Jinja 2, one of the arguments to the function "catch" here is 
"caller", which when called invokes the body (and can be called multiple 
times with different arguments)


I started out with Tempita because it's so simple to ship, but the lack 
of a call-block construct + the inability to break lines where I wanted 
drove me crazy.


Then I tried Mako, because it has the largest set of features, but the 
syntax was simply too gruesome. I first tried to ignore this, but simply 
couldn't, it made my code totally unreadable.


Finally, Jinja2 has most of what I need. Slight disadvantage is it tries 
to be "pure" and not allow too much arbitrary Python,


Ideally what I'd like is something like Tempita but developed further to 
allow line-breaks and call-blocks, but lacking that I use Jinja2.


I don't remember why I didn't like Cheetah (perhaps it doesn't do 
call-blocks?)


Dag
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Wacky idea: proper macros

2012-05-01 Thread Dag Sverre Seljebotn

On 05/01/2012 10:29 AM, Dag Sverre Seljebotn wrote:

On 04/30/2012 11:36 PM, William Stein wrote:

On Mon, Apr 30, 2012 at 2:32 PM, Dag Sverre Seljebotn
 wrote:



Wes McKinney wrote:


On Mon, Apr 30, 2012 at 4:55 PM, Nathaniel Smith wrote:

On Mon, Apr 30, 2012 at 9:49 PM, Dag Sverre Seljebotn
 wrote:

JIT is really the way to go. It is one thing that a JIT could

optimize the

case where you pass a callback to a function and inline it run-time.

But

even if it doesn't get that fancy, it'd be great to just be able to

write

something like "cython.eval(s)" and have that be compiled (I guess

you could

do that now, but the sheer overhead of the C compiler and all the

.so files

involved means nobody would sanely use that as the main way of

stringing

together something like pandas).


The overhead of running a fully optimizing compiler over pandas on
every import is pretty high, though. You can come up with various
caching mechanisms, but they all mean introducing some kind of

compile

time/run time distinction. So I'm skeptical we'll just be able to get
rid of that concept, even in a brave new LLVM/PyPy/Julia world.

-- Nathaniel
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


I'd be perfectly OK with just having to compile pandas's "data engine"
and generate loads of C/C++ code. JIT-compiling little array
expressions would be cool too. I've got enough of an itch that I might
have to start scratching pretty soon.


I think a good start is:

Myself I'd look into just using Jinja2 to generate all the Cython
code, rather than those horrible Python interpolated strings...that
should give you something that's at least rather pleasant for you to
work with once you are used to it (even if it is a bit horrible to
newcomers to the code base).

You can even check in the generated sources.

And we've discussed letting cython be smart with templating languages
and error report on a line in the original template, such features
will certainly accepted once somebody codes it up.

(I can give you me breakdown of how I eliminate other templating
languages than Jinja2 for this purpose tomorrow if you are interested).


Can you point us to a good example of you using jinja2 for this purpose?


Sure, I just needed some sleep...

I only use it for C code, haven't used it for Cython so far (I tend to
write things in C and wrap it in Cython).

1)

https://github.com/dagss/elemental4py/blob/master/src/elemental_wrapper.cpp.in


(work-in-progress) Here I use Jinja2 to write a C wrapper around
Elemental (Elemental is a library for dense linear algebra over MPI).
The C++ library is a heavy user of templates, I replace the templates
with run-time dispatches using if-tests, so that rather than
"DistMatrix" you have an elem_matrix struct with
ELEM_DOUBLE, ELEM_MC, ELEM_MR.

2)

https://github.com/wavemoth/wavemoth/blob/master/src/legendre_transform.c.in


This is a numerical kernel where I do loop unrolling etc. using
metaprogramming (with Tempita, not Jinja2).

https://github.com/wavemoth/wavemoth/blob/cuda/wavemoth/cuda/legendre_transform.cu.in


3)

https://github.com/wavemoth/wavemoth/blob/cuda/wavemoth/cuda/legendre_transform.cu.in


Numerical kernel in templated CUDA using Tempita.

On templating languages I tried)

I've scanned through a few and actually tried Tempita, Mako, Jinja2.

The features I need:

- Pythonic syntax and ability to embed arbitrary Python code

- A "call-block", such as this

{% call catch('A->grid->ctx') %}
BODY
{% endcall %}


i.e. in Jinja 2, one of the arguments to the function "catch" here is
"caller", which when called invokes the body (and can be called multiple
times with different arguments)

I started out with Tempita because it's so simple to ship, but the lack
of a call-block construct + the inability to break lines where I wanted
drove me crazy.

Then I tried Mako, because it has the largest set of features, but the
syntax was simply too gruesome. I first tried to ignore this, but simply
couldn't, it made my code totally unreadable.

Finally, Jinja2 has most of what I need. Slight disadvantage is it tries
to be "pure" and not allow too much arbitrary Python,


[sorry:] Slight disadvantage is it tries to be "pure" and not allow too 
much arbitrary Python, but one can work around that by using an 
auxiliary Python module and pass that Python module to the template when 
instantiating it -- so one kind of can use arbitrary Python in the 
templating process, one just need to edit separate files. (Which is 
perhaps better -- I'm unable to make up my mind on such trivial issues.)


Dag



Ideally what I'd like is something like Tempita but developed further to
allow line-breaks and call-blocks, but lacking that I use Jinja2.

I don't remember why I didn't like Cheetah (perhaps it doesn't do
call-blocks?)

Dag


___
cython-devel mailing list
cytho

Re: [Cython] [cython-users] Conditional import in pure Python mode

2012-05-01 Thread Stefan Behnel
>>> On 29 April 2012 01:33, Ian Bell wrote:
 idiom like

 if cython.compiled:
 cython.import('from libc.math cimport sin')
 else:
 from math import sin

Actually, in this particular case, I would even accept a solution that
special cases the "math" module internally by automatically cimporting
libc.math as an override (or rather an adapted version as plain "math.pxd").

This CEP describes a general approach:

http://wiki.cython.org/enhancements/overlaypythonmodules

It's partly outdated, so things may have become easier these days.

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] [cython-users] Conditional import in pure Python mode

2012-05-01 Thread Stefan Behnel
Ian Bell, 01.05.2012 15:50:
> On Tue, May 1, 2012 at 9:21 PM, Stefan Behnel wrote:
> On 29 April 2012 01:33, Ian Bell wrote:
>> idiom like
>>
>> if cython.compiled:
>> cython.import('from libc.math cimport sin')
>> else:
>> from math import sin
>>
>> Actually, in this particular case, I would even accept a solution that
>> special cases the "math" module internally by automatically cimporting
>> libc.math as an override (or rather an adapted version as plain
>> "math.pxd").
>>
>> This CEP describes a general approach:
>>
>> http://wiki.cython.org/enhancements/overlaypythonmodules
>>
>> It's partly outdated, so things may have become easier these days.
> 
> That is exactly what I was looking for.  If we could implement that, it
> would solve all my problems.  It would meet all my needs - on this front at
> least.

There are two things to do here:

1) Write up a math.pxd that contains declarations equivalent to Python's
math module. Note that this may not be entirely trivial because the math
module does some error handling and type special casing under the hood.
Some of this may still be required for the C level equivalents, although
the type special casing would better be done by overriding function
signatures using this feature:

http://docs.cython.org/src/userguide/external_C_code.html#resolving-naming-conflicts-c-name-specifications

Basically, you would declare two (or more) function signatures under the
same name, but with different C names.

2) Use math.pxd as an override for the math module. I'm not sure yet how
that would best be made to work, but it shouldn't be all that complex. It
already works (mostly?) for numpy.pxd, for example, although that's done
explicitly in user code.

I think we should start with 2) to see how to get this to work in general,
before we put too much work into 1).

Could you sign up for the cython-devel mailing list please, so that we can
coordinate the work there?

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Conditional import in pure Python mode

2012-05-01 Thread Stefan Behnel
Stefan Behnel, 01.05.2012 21:14:
> 2) Use math.pxd as an override for the math module. I'm not sure yet how
> that would best be made to work, but it shouldn't be all that complex. It
> already works (mostly?) for numpy.pxd, for example, although that's done
> explicitly in user code.

BTW, I think it would be helpful to make the numpy.pxd cimport automatic as
well whenever someone does "import numpy" and friends, right?

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Conditional import in pure Python mode

2012-05-01 Thread mark florisson
On 1 May 2012 20:22, Stefan Behnel  wrote:
> Stefan Behnel, 01.05.2012 21:14:
>> 2) Use math.pxd as an override for the math module. I'm not sure yet how
>> that would best be made to work, but it shouldn't be all that complex. It
>> already works (mostly?) for numpy.pxd, for example, although that's done
>> explicitly in user code.
>
> BTW, I think it would be helpful to make the numpy.pxd cimport automatic as
> well whenever someone does "import numpy" and friends, right?
>
> Stefan
> ___
> cython-devel mailing list
> cython-devel@python.org
> http://mail.python.org/mailman/listinfo/cython-devel

I'm not sure, it means the user has to have numpy development headers.
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Conditional import in pure Python mode

2012-05-01 Thread Francesc Alted

On 5/1/12 2:39 PM, mark florisson wrote:

On 1 May 2012 20:22, Stefan Behnel  wrote:

Stefan Behnel, 01.05.2012 21:14:

2) Use math.pxd as an override for the math module. I'm not sure yet how
that would best be made to work, but it shouldn't be all that complex. It
already works (mostly?) for numpy.pxd, for example, although that's done
explicitly in user code.

BTW, I think it would be helpful to make the numpy.pxd cimport automatic as
well whenever someone does "import numpy" and friends, right?

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel

I'm not sure, it means the user has to have numpy development headers.


But if the user is going to compile a NumPy application, it sounds like 
strange to me that she should not be required to install the NumPy 
development headers, right?


--
Francesc Alted

___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Conditional import in pure Python mode

2012-05-01 Thread Stefan Behnel
mark florisson, 01.05.2012 21:39:
> On 1 May 2012 20:22, Stefan Behnel wrote:
>> Stefan Behnel, 01.05.2012 21:14:
>>> 2) Use math.pxd as an override for the math module. I'm not sure yet how
>>> that would best be made to work, but it shouldn't be all that complex. It
>>> already works (mostly?) for numpy.pxd, for example, although that's done
>>> explicitly in user code.
>>
>> BTW, I think it would be helpful to make the numpy.pxd cimport automatic as
>> well whenever someone does "import numpy" and friends, right?
> 
> I'm not sure, it means the user has to have numpy development headers.

Hmm, right. What about making it an explicit compile time option then?
Something like

  # cython: override_modules = math,numpy

Or should we go for an opt-out?

  # cython: python_modules = math,numpy

Sounds like it would hit the more common case by default.

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Conditional import in pure Python mode

2012-05-01 Thread Stefan Behnel
Francesc Alted, 01.05.2012 21:49:
> On 5/1/12 2:39 PM, mark florisson wrote:
>> On 1 May 2012 20:22, Stefan Behnel wrote:
>>> Stefan Behnel, 01.05.2012 21:14:
 2) Use math.pxd as an override for the math module. I'm not sure yet how
 that would best be made to work, but it shouldn't be all that complex. It
 already works (mostly?) for numpy.pxd, for example, although that's done
 explicitly in user code.
>>> BTW, I think it would be helpful to make the numpy.pxd cimport automatic as
>>> well whenever someone does "import numpy" and friends, right?
>>>
>> I'm not sure, it means the user has to have numpy development headers.
> 
> But if the user is going to compile a NumPy application, it sounds like
> strange to me that she should not be required to install the NumPy
> development headers, right?

Let's say it's not impossible that someone uses NumPy and Cython without
any accelerated C level connection between the two, but it's rather
unlikely, given that Cython already has all dependencies that this
connection would require as well, except for the NumPy header files.

So I would suggest to make the automatic override the default for any
module for which a .pxd file with the same fully qualified name is found in
the search path, and to require users to explicitly disable this feature
for a given module using a module level (or external) compiler directive if
they feel like getting slower code (or working around a bug or whatever).

Anyway, given that this feature isn't even implemented yet, it may appear a
bit premature to discuss these details.

Stefan
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Conditional import in pure Python mode

2012-05-01 Thread Robert Bradshaw
On Tue, May 1, 2012 at 1:02 PM, Stefan Behnel  wrote:
> Francesc Alted, 01.05.2012 21:49:
>> On 5/1/12 2:39 PM, mark florisson wrote:
>>> On 1 May 2012 20:22, Stefan Behnel wrote:
 Stefan Behnel, 01.05.2012 21:14:
> 2) Use math.pxd as an override for the math module. I'm not sure yet how
> that would best be made to work, but it shouldn't be all that complex. It
> already works (mostly?) for numpy.pxd, for example, although that's done
> explicitly in user code.

math.pxd would be a bit trickier, as we're trying to shadow python
functions with independent c implementations (rather than declaring
structure to the single numpy array object and exposing c-level only
methods. We'd need to support stuff like

double x = ...
double y = sin(x) # fast
cdef object f = sin # grab the builtin one?

but this is by no means insurmountable and could be really useful.

 BTW, I think it would be helpful to make the numpy.pxd cimport automatic as
 well whenever someone does "import numpy" and friends, right?

>>> I'm not sure, it means the user has to have numpy development headers.
>>
>> But if the user is going to compile a NumPy application, it sounds like
>> strange to me that she should not be required to install the NumPy
>> development headers, right?
>
> Let's say it's not impossible that someone uses NumPy and Cython without
> any accelerated C level connection between the two, but it's rather
> unlikely, given that Cython already has all dependencies that this
> connection would require as well, except for the NumPy header files.
>
> So I would suggest to make the automatic override the default for any
> module for which a .pxd file with the same fully qualified name is found in
> the search path, and to require users to explicitly disable this feature
> for a given module using a module level (or external) compiler directive if
> they feel like getting slower code (or working around a bug or whatever).

There is another consideration: this can introduce unnecessary and
potentially costly dependencies. For example, in Sage one has
sage/rings/integer.pxd. Not everything that imports from this file
needs c-level access to the Integer type, and requiring everything
that imports from sage.rings.integer to be re-compiled when this file
changes would increase the (admittedly already lengthy) re-compile, as
well as sucking in a (chain of) un-needed declarations. As Cython
becomes more and more common, a similar effect could happen between
projects as well.

This may be the exception rather than the rule, so perhaps it's not
*that* bad to let opt-in be the default, i.e.

# cython: cimport_on_import = __all__


- Robert
___
cython-devel mailing list
cython-devel@python.org
http://mail.python.org/mailman/listinfo/cython-devel