Repository: numba/numba

Issue:
Build failed: fatal error: omp.h: No such file or directory
<!--

Thanks for opening an issue! To help the Numba team handle your information
efficiently, please first ensure that there is no other issue present that
already describes the issue you have
(search at https://github.com/numba/numba/issues?&q=is%3Aissue).

For more general "how do I do X?" type questions, please speak to us in real
time on https://gitter.im/numba/numba or post to the Numba mailing list
https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [x] I am using the latest released version of Numba (most recent is visible in
 the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).
- [x] I have included below a minimal working reproducer (if you are unsure how
 to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).

<!--

Please include details of the bug here, including, if applicable, what you
expected to happen!

-->

I have added python3, python-llvmlite, python-numpy dependencies for numba-0.48.0 version. Build is failing due to missing omp.h please check this [numba_build_log](https://paste.ubuntu.com/p/9V7HKnvtfr/) 


Discussion:
Look like it an openmp requirement, any flag to disable to openmp during build. I have tried --disable-openmp but no use.
Enabling openmp support on toolchain seems building fine, but failed to import at target.

$ python --version
Python 3.8.1
$ python3 -c "import llvmlite"
$ pip show llvmlite
Name: llvmlite
Version: 0.31.0
Summary: lightweight wrapper around basic LLVM functionality
Home-page: http://llvmlite.pydata.org
Author: Continuum Analytics, Inc.
Author-email: numba-users@continuum.io
License: BSD
Location: /usr/lib/python3.8/site-packages
Requires: 
Required-by: numba
$ python3 -c "import numpy"
$ pip show numpy
Name: numpy
Version: 1.18.1
Summary: NumPy is the fundamental package for array computing with Python.
Home-page: https://www.numpy.org
Author: Travis E. Oliphant et al.
Author-email: None
License: BSD
Location: /usr/lib/python3.8/site-packages
Requires: 
Required-by: scikit-learn, resampy, numba, matplotlib, librosa
$ python3 -c "import numba"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.8/site-packages/numba/__init__.py", line 48, in <module>
    import numba.charseq
  File "/usr/lib/python3.8/site-packages/numba/charseq.py", line 6, in <module>
    from numba import types, cgutils, unicode
  File "/usr/lib/python3.8/site-packages/numba/unicode.py", line 32, in <module>
    from numba.targets.hashing import _Py_hash_t
  File "/usr/lib/python3.8/site-packages/numba/targets/hashing.py", line 632, in <module>
    raise NotImplementedError("FNV hashing is not implemented")
NotImplementedError: FNV hashing is not implemented

Look like the numba/targets/hashing.py is looking for siphash24 and I enabled both siphash, csiphash and siphashc modules as well but still have the same error.

$ pip show siphash
Name: siphash
Version: 0.0.1
Summary: siphash - python siphash implementation
Home-page: http://github.com/majek/pysiphash#readme
Author: Marek Majkowski
Author-email: marek@popcount.org
License: MIT
Location: /usr/lib/python3.8/site-packages
Requires: 
Required-by: 


Any comments?

Thanks for the report. Yes, OpenMP headers and runtime are needed on Linux at compile time, in part because at present we have no way of easily asking the question "does this system have OpenMP", this is probably something to look at. For now I'll update the docs saying that it is required.
RE: siphash24

Numba is looking at the CPython build to see if `siphash24` is the hashing alg in use internally in CPython. For example, Anaconda distribution CPython has the hash algorithm set as `'siphash24'`, 
```pycon
In [1]: import sys                                                                                                              

In [2]: sys.hash_info.algorithm                                                                                                 
Out[2]: 'siphash24'
```
This is because Anaconda CPython is compiled with it enabled (as signaled by this flag at compile time https://github.com/python/cpython/blob/e263bb1e97ae8f84fb4f2ab5b0c4f529a2e5696d/configure#L1532-L1534).

I'm thinking that for a Python with no `siphash24`, it might be best to issue a loud warning that hash values won't match those computed in the Python interpreter and then just switch to using `siphash` i.e. implement the `TODO` here:
https://github.com/numba/numba/blob/a4c4a8dceb0801672d6fda9199c36047dba16f0b/numba/cpython/hashing.py#L612-L614
Common use cases for hashing, like dictionaries, wouldn't be affected by such a change, it would only be cases where the specific value of the hash matters.
I should also add that this is the first use case in the wild I've seen where `siphash24` is not in use, any idea why this is the case? See [PEP 456](https://www.python.org/dev/peps/pep-0456/) for the [rational for change](https://www.python.org/dev/peps/pep-0456/#rationale) behind its use, the [conclusion](https://www.python.org/dev/peps/pep-0456/#conclusion) is:
> SipHash provides the best combination of speed and security. Developers of other prominent projects have came to the same conclusion.


Resolving patch:
diff --git a/numba/cpython/hashing.py b/numba/cpython/hashing.py
--- a/numba/cpython/hashing.py
+++ b/numba/cpython/hashing.py
@@ -6,6 +6,7 @@
 import numpy as np
 import sys
 import ctypes
+import warnings
 from collections import namedtuple
 
 import llvmlite.binding as ll
@@ -460,7 +461,22 @@ def inject(name, val):
 # ------------------------------------------------------------------------------
 
 
-if _Py_hashfunc_name == 'siphash24':
+if _Py_hashfunc_name in ('siphash24', 'fnv'):
+
+    # Check for use of the FNV hashing alg, warn users that it's not implemented
+    # and functionality relying of properties derived from hashing will be fine
+    # but hash values themselves are likely to be different.
+    if _Py_hashfunc_name == 'fnv':
+        msg = ("FNV hashing is not implemented in Numba. See PEP 456 "
+               "https://www.python.org/dev/peps/pep-0456/ "
+               "for rationale over not using FNV. Numba will continue to work, "
+               "but hashes for built in types will be computed using "
+               "siphash24. This will permit e.g. dictionaries to continue to "
+               "behave as expected, however anything relying on the value of "
+               "the hash opposed to hash as a derived property is likely to "
+               "not work as expected.")
+        warnings.warn(msg)
+
     # This is a translation of CPython's siphash24 function:
     # https://github.com/python/cpython/blob/d1dd6be613381b996b9071443ef081de8e5f3aff/Python/pyhash.c#L287-L413    # noqa: E501
 
@@ -608,10 +624,6 @@ def _siphash24(k0, k1, src, src_sz):
         v0, v1, v2, v3 = _DOUBLE_ROUND(v0, v1, v2, v3)
         t = (v0 ^ v1) ^ (v2 ^ v3)
         return t
-
-elif _Py_hashfunc_name == 'fnv':
-    # TODO: Should this instead warn and switch to siphash24?
-    raise NotImplementedError("FNV hashing is not implemented")
 else:
     msg = "Unsupported hashing algorithm in use %s" % _Py_hashfunc_name
     raise ValueError(msg)


Test patch:
diff --git a/numba/tests/test_hashing.py b/numba/tests/test_hashing.py
--- a/numba/tests/test_hashing.py
+++ b/numba/tests/test_hashing.py
@@ -6,7 +6,9 @@
 import unittest
 
 import sys
+import subprocess
 from collections import defaultdict
+from textwrap import dedent
 
 import numpy as np
 
@@ -23,6 +25,47 @@ def hash_usecase(x):
     return hash(x)
 
 
+class TestHashingSetup(TestCase):
+
+    def test_warn_on_fnv(self):
+        # FNV hash alg variant is not supported, check Numba warns
+        work = """
+        import sys
+        import warnings
+        from collections import namedtuple
+
+        # hash_info is a StructSequence, mock as a named tuple
+        fields = ["width", "modulus", "inf", "nan", "imag", "algorithm",
+                  "hash_bits", "seed_bits", "cutoff"]
+
+        hinfo = sys.hash_info
+        FAKE_HASHINFO = namedtuple('FAKE_HASHINFO', fields)
+
+        fd = dict()
+        for f in fields:
+            fd[f] = getattr(hinfo, f)
+
+        fd['algorithm'] = 'fnv'
+
+        fake_hashinfo = FAKE_HASHINFO(**fd)
+
+        # replace the hashinfo with the fnv version
+        sys.hash_info = fake_hashinfo
+        with warnings.catch_warnings(record=True) as warns:
+            # Cause all warnings to always be triggered.
+            warnings.simplefilter("always")
+            import numba
+            assert len(warns) > 0
+            expect = "FNV hashing is not implemented in Numba. See PEP 456"
+            for w in warns:
+                if expect in str(w.message):
+                    break
+            else:
+                raise RuntimeError("Expected warning not found")
+        """
+        subprocess.check_call([sys.executable, '-c', dedent(work)])
+
+
 class BaseTest(TestCase):
 
     def setUp(self):