althonos / pyhmmer

Cython bindings and Python interface to HMMER3.
https://pyhmmer.readthedocs.io
MIT License
120 stars 12 forks source link

PyHmmer sets CPU float behaviour globally, potentially causing issues in other libraries #71

Open jakobnissen opened 1 month ago

jakobnissen commented 1 month ago

When loading pyhmmer v0.10.12 together with NumPy v1.26.4, the following warning are printed to the screen:

/home/jakni/miniconda3/envs/vamb312/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
  setattr(self, word, getattr(machar, word).flat[0])
/home/jakni/miniconda3/envs/vamb312/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
  return self._float_to_str(self.smallest_subnormal)
/home/jakni/miniconda3/envs/vamb312/lib/python3.12/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
  setattr(self, word, getattr(machar, word).flat[0])
/home/jakni/miniconda3/envs/vamb312/lib/python3.12/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
  return self._float_to_str(self.smallest_subnormal)

From a bit of googling, this is what I found out:

It looks like C libraries compiled with either -Ofast or -ffast-math will cause the C library to set this flag when loaded.

Apart from the annoying warning, it is unsafe, and also completely unreasonable that loading one library will globally affect the CPU's behaviour for the whole process, including all other libraries. I narrowed it down to pyhmmer 0.10.12.

This can be solved by compiling pyhmmer without these flags.

althonos commented 1 month ago

This is unfortunately a known problem (#38) with the CPython binaries distributed in the cibuildwheel containers, where some of them were indeed compiled with -ffast-math for some reason, and the flags were then getting into the default compilation flags reported by sysconfig and used by default in the setup.py script...