raysect / source

The main source repository for the Raysect project.
http://www.raysect.org
BSD 3-Clause "New" or "Revised" License
88 stars 23 forks source link

Cython 3.0a6 causes hangs with function framework #373

Open jacklovell opened 3 years ago

jacklovell commented 3 years ago

Cython 3.0a6 has changed the way binary operators such as __add__ are implemented: https://cython.readthedocs.io/en/latest/src/changes.html#alpha-6-2020-07-31. They now follow Python semantics rather than the C API semantics. This has caused issues with using the function objects in Raysect. For example:

from raysect.core.math.function.float import Arg2D, Exp2D
f = Exp2D(Arg2D('x'))
f * 2  # Returns MultiplyFunction2D instantly
2 * f  # Hangs at 100% CPU

I've been able to fix this by adding the c_api_binop_methods=True Cython directive to raysect's setup.py, but I don't know if this is a backwards-compatible solution. The alternative is to implement __radd__ etc. in the function frameworks: these will be ignored by Cython 0.x and the old behaviour maintained, whereas in Cython 3.x these functions will be called. They can just call the existing __add__ etc. functions with the arguments in the correct order.

vsnever commented 3 years ago

I ran into this issue a couple of weeks ago on the JET cluster, but didn't link it to a Cython change, unfortunately. I thought it was some kind of local system bug.

vsnever commented 3 years ago

By the way, this affects not only the function framework, but the entire math framework: points, vectors, quaternions, affine matrices.

CnlPepper commented 3 years ago

We'll need to rewrite these sections when Cython 3 is released. There are likely to be more changes than just radd. It would be best to tackle them in one update.

jacklovell commented 3 years ago

Recent Cython alpha releases have fixed the hang. 2 * f in the above example now fails immediately with a TypeError:

>>> 2 * f
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'int' and 'raysect.core.math.function.float.function2d.cmath.Exp2D'

Applying the c_api_binop_methods directive still fixes the issue.