modulus operator

376 views
Skip to first unread message

JF Gallant

unread,
Feb 26, 2013, 7:20:31 AM2/26/13
to cython...@googlegroups.com
Hi !

I write a code with modulus operator like :

a = b % 3

but every lines like that output yellow color in the html file. This is fully converted in C ?


thanks a lot,

JF

Lars Buitinck

unread,
Feb 26, 2013, 7:30:47 AM2/26/13
to cython...@googlegroups.com
2013/2/26 JF Gallant <pyro...@gmail.com>:
> a = b % 3
>
> but every lines like that output yellow color in the html file. This is fully converted in C ?

No, this is converted to a modulo with Python semantics, including a
ZeroDivisionError. Use @cython.cdivision(True) to get C-style modulo.
For details, see:
http://wiki.cython.org/enhancements/compilerdirectives

--
Lars Buitinck
Scientific programmer, ILPS
University of Amsterdam

Sturla Molden

unread,
Feb 26, 2013, 7:34:09 AM2/26/13
to cython...@googlegroups.com
On 26.02.2013 13:20, JF Gallant wrote:
> Hi !
>
> I write a code with modulus operator like :
>
> a = b % 3
>
> but every lines like that output yellow color in the html file. This is fully converted in C ?

Python and C have slightly different integer division and modulus
operators for signed integers. Python follows the mathematical
definition and rounds towards infinity, whereas C rounds towards zero.
So -1 % 5 is 4 in Python and -1 in C. 4 is the mathematically "correct"
result.

Cython by default follows Python's behavior.

If you want C behavior for integer division and modulus, use this decorator:

cimport cython
@cython.cdivision(True)



Sturla

Sturla Molden

unread,
Feb 26, 2013, 7:46:23 AM2/26/13
to cython...@googlegroups.com
On 26.02.2013 13:20, JF Gallant wrote:
> This is fully converted in C ?

It is fully converted to C, but it takes slightly more C code than just
inserting the / or % operator into C. On x86 it will typically incur a
20% speed overhead compared to using the C operators directly.

On the other hand, pure C operators will not always give the
mathematically correct result, and they are not fully compatible with
Python's semantics.


Sturla







JF Gallant

unread,
Feb 26, 2013, 8:23:39 AM2/26/13
to cython...@googlegroups.com

So , if I never get under zero and my operation stay simple , I can use cdivision to get a bit of speed.
I just want to switch between 0,1,2  ( x,y,z axis ) depends on the depth for my simple kdtree implementation.
I will see if they can cause problem and if the speed gain is correct.


Sturla Molden

unread,
Feb 26, 2013, 8:42:48 AM2/26/13
to cython...@googlegroups.com
On 26.02.2013 14:23, JF Gallant wrote:

> So , if I never get under zero and my operation stay simple , I can use
> cdivision to get a bit of speed.

If you only have positive integers it should not matter. If you have
signed integers you can use cdivision to get some extra speed for the
cost of mathematical correctness. But it is very rare that integer
division or modulus operators matters for the performance of an
algorithm. Examples are random number generators, compression
algorithms, or encryption/decryption, ring-buffers, and other stuff that
depends heavily on division or modulus.

> I just want to switch between 0,1,2 ( x,y,z axis ) depends on the depth
> for my simple kdtree implementation.
> I will see if they can cause problem and if the speed gain is correct.

That is speed-gain for the division, not speed gain for the whole
program! Usually it never matters, because it is just a tiny tiny part
of the run-time. For the purpose you describe here I can almost
guarantee you it will not see any difference. Premature optimization
serves no purpose. If you were writing a high-performance encryption
algorithm it could matter. If you were using modulus for indexing into a
ring-buffer in digital signal processing it could matter. But not for
swapping the splitting axis in a kd-tree.

Sturla



JF Gallant

unread,
Feb 26, 2013, 9:16:00 AM2/26/13
to cython...@googlegroups.com

yes that's true. Probably have more critical part to optimise after then the modulus thing.
But I'm just aware if can cause problem if I want to nogil this part of code for eventually make it parallelizable.

Sturla Molden

unread,
Feb 26, 2013, 9:21:46 AM2/26/13
to cython...@googlegroups.com
On 26.02.2013 15:16, JF Gallant wrote:

> yes that's true. Probably have more critical part to optimise after then
> the modulus thing.
> But I'm just aware if can cause problem if I want to nogil this part of
> code for eventually make it parallelizable.

nogil does not require cython.cdivision(True).


Sturla




Robert Bradshaw

unread,
Feb 26, 2013, 1:39:34 PM2/26/13
to cython...@googlegroups.com
It should, as it also does a zero-division check (possibly raising a
ZeroDivisionError). But in terms of performance, this is almost
certainly un-measurable premature optimization (and can lead to
surprising behavior, like dict[k%n] having 2*n-1 entries, not just n
entries, as you vary over k).

- Robert

Stefan Behnel

unread,
Feb 27, 2013, 3:03:48 AM2/27/13
to cython...@googlegroups.com
Robert Bradshaw, 26.02.2013 19:39:
> On Tue, Feb 26, 2013 at 6:21 AM, Sturla Molden wrote:
>> On 26.02.2013 15:16, JF Gallant wrote:
>>
>>> yes that's true. Probably have more critical part to optimise after then
>>> the modulus thing.
>>> But I'm just aware if can cause problem if I want to nogil this part of
>>> code for eventually make it parallelizable.
>
>> nogil does not require cython.cdivision(True).
>
> It should, as it also does a zero-division check (possibly raising a
> ZeroDivisionError).

Not sure if you mean what you are writing. I don't think a "nogil" section
should change division semantics all by itself. But we'd have to acquire
the GIL for raising the exception. Since that won't normally happen, it
would just add a bit of unlikely() code, shouldn't hurt otherwise, as the C
compiler will just move it out of the way as it does for the current code.


> But in terms of performance, this is almost
> certainly un-measurable premature optimization (and can lead to
> surprising behavior, like dict[k%n] having 2*n-1 entries, not just n
> entries, as you vary over k).

Absolutely.

Stefan

Robert Bradshaw

unread,
Feb 27, 2013, 3:43:08 AM2/27/13
to cython...@googlegroups.com
On Wed, Feb 27, 2013 at 12:03 AM, Stefan Behnel <stef...@behnel.de> wrote:
> Robert Bradshaw, 26.02.2013 19:39:
>> On Tue, Feb 26, 2013 at 6:21 AM, Sturla Molden wrote:
>>> On 26.02.2013 15:16, JF Gallant wrote:
>>>
>>>> yes that's true. Probably have more critical part to optimise after then
>>>> the modulus thing.
>>>> But I'm just aware if can cause problem if I want to nogil this part of
>>>> code for eventually make it parallelizable.
>>
>>> nogil does not require cython.cdivision(True).
>>
>> It should, as it also does a zero-division check (possibly raising a
>> ZeroDivisionError).
>
> Not sure if you mean what you are writing. I don't think a "nogil" section
> should change division semantics all by itself. But we'd have to acquire
> the GIL for raising the exception. Since that won't normally happen, it
> would just add a bit of unlikely() code, shouldn't hurt otherwise, as the C
> compiler will just move it out of the way as it does for the current code.

Yes, that's how it should be, but wasn't until
https://github.com/cython/cython/commit/9dabf9a613805fae1c292c10986e2b0593e4dbd8

- Robert
Reply all
Reply to author
Forward
0 new messages