From 729b1f6d4ad8af3652effe50fa60ec6d691f6154 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Sun, 23 May 2021 22:34:01 -0500 Subject: [PATCH 1/4] Fixed issue/14 1. Use `pthread_atfork` to restore MKL threading layer environment variable set by init code for the forked process. 2. Fixed multiple GCC compiler warnings. --- mkl/_mklinitmodule.c | 51 ++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/mkl/_mklinitmodule.c b/mkl/_mklinitmodule.c index 6dc5856..38a3317 100644 --- a/mkl/_mklinitmodule.c +++ b/mkl/_mklinitmodule.c @@ -10,6 +10,7 @@ #define _GNU_SOURCE 1 #include #include +#include #undef _GNU_SOURCE #endif @@ -29,17 +30,33 @@ static struct PyMethodDef methods[] = { #define MKL_SERVICE_INLINE inline #endif -static MKL_SERVICE_INLINE void _set_mkl_ilp64(); -static MKL_SERVICE_INLINE void _set_mkl_lp64(); -static MKL_SERVICE_INLINE void _set_mkl_interface(); +static MKL_SERVICE_INLINE void _set_mkl_ilp64(void); +static MKL_SERVICE_INLINE void _set_mkl_lp64(void); +static MKL_SERVICE_INLINE void _set_mkl_interface(void); + +static const char* mtlayer; +static const char* verbose; -static void _preload_threading_layer() { #if FORCE_PRELOADING #define VERBOSE(...) if(verbose) printf("mkl-service + Intel(R) MKL: " __VA_ARGS__) -#define SET_MTLAYER(L) do { \ +static void restore_mtlayer(void) { + if (mtlayer) { + VERBOSE("Re-setting Intel(R) MKL_THREADING_LAYER=%s for the forked process\n", mtlayer); \ + setenv("MKL_THREADING_LAYER", mtlayer, 1); + } else { + VERBOSE("Unsetting Intel(R) MKL_THREADING_LAYER variable for the forked process \n"); \ + unsetenv("MKL_THREADING_LAYER"); + } +} +#endif + +static void _preload_threading_layer(void) { +#if FORCE_PRELOADING +#define SET_MTLAYER(L) do { \ VERBOSE("setting Intel(R) MKL to use " #L " OpenMP runtime\n"); \ mkl_set_threading_layer(MKL_THREADING_##L); \ setenv("MKL_THREADING_LAYER", #L, 0); \ + pthread_atfork(NULL, NULL, &restore_mtlayer); \ } while(0) #define PRELOAD(lib) do { \ VERBOSE("preloading %s runtime\n", lib); \ @@ -47,12 +64,12 @@ static void _preload_threading_layer() { } while(0) /* * The following is the pseudo-code skeleton for reinterpreting unset MKL_THREADING_LAYER - * + * * if MKL_THREADING_LAYER is empty * if kmp_calloc (or a suitable symbol identified by Terry) is loaded, * we are using Intel(R) OpenMP, i.e. reinterpret as implicit value of INTEL * otherwise check if other Open MP is loaded by checking get_omp_num_threads symbol - * if not loaded: + * if not loaded: * assume INTEL, and force loading of IOMP5 * if loaded: * if Gnu OMP, set MKL_THREADING_LAYER=GNU, and call set_mkl_threading_layer(MKL_THREADING_GNU) @@ -65,8 +82,14 @@ static void _preload_threading_layer() { */ const char *libiomp = "libiomp5.so"; - const char *verbose = getenv("MKL_VERBOSE"); - const char *mtlayer = getenv("MKL_THREADING_LAYER"); + verbose = getenv("MKL_VERBOSE"); + mtlayer = getenv("MKL_THREADING_LAYER"); + + /* Use of RTLD_DEFAULT handler is to indicate that symbol is being lookup-up among symbols + * presently known to this process. + * + * See: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dlsym.html + */ void *omp = dlsym(RTLD_DEFAULT, "omp_get_num_threads"); const char *omp_name = "(unidentified)"; const char *iomp = NULL; /* non-zero indicates Intel(R) OpenMP is loaded */ @@ -108,21 +131,21 @@ static void _preload_threading_layer() { return; } -static MKL_SERVICE_INLINE void _set_mkl_ilp64() { +static MKL_SERVICE_INLINE void _set_mkl_ilp64(void) { #ifdef USING_MKL_RT - int i = mkl_set_interface_layer(MKL_INTERFACE_ILP64); + mkl_set_interface_layer(MKL_INTERFACE_ILP64); #endif return; } -static MKL_SERVICE_INLINE void _set_mkl_lp64() { +static MKL_SERVICE_INLINE void _set_mkl_lp64(void) { #ifdef USING_MKL_RT - int i = mkl_set_interface_layer(MKL_INTERFACE_LP64); + mkl_set_interface_layer(MKL_INTERFACE_LP64); #endif return; } -static MKL_SERVICE_INLINE void _set_mkl_interface() { +static MKL_SERVICE_INLINE void _set_mkl_interface(void) { _set_mkl_lp64(); _preload_threading_layer(); } From ec29aeba7ae174b3546a3517951ca9753f731c78 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Sun, 23 May 2021 22:35:52 -0500 Subject: [PATCH 2/4] Drop support for Python 2 1. Remove use of six, and remove mention of its requirement in setup 2. No longer attempt to infer MKL location from numpy's distutils Always require MKLROOT variable to be set. --- setup.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 4b6f157..bfff9c8 100644 --- a/setup.py +++ b/setup.py @@ -60,16 +60,12 @@ def get_extensions(): - try: - from numpy.distutils.system_info import get_info - mkl_info = get_info('mkl') - except ImportError: - mkl_root = os.environ['MKLROOT'] - mkl_info = { - 'include_dirs': [join(mkl_root, 'include')], - 'library_dirs': [join(mkl_root, 'lib'), join(mkl_root, 'lib', 'intel64')], - 'libraries': ['mkl_rt'] - } + mkl_root = os.environ['MKLROOT'] + mkl_info = { + 'include_dirs': [join(mkl_root, 'include')], + 'library_dirs': [join(mkl_root, 'lib'), join(mkl_root, 'lib', 'intel64')], + 'libraries': ['mkl_rt'] + } mkl_include_dirs = mkl_info.get('include_dirs', []) mkl_library_dirs = mkl_info.get('library_dirs', []) @@ -99,7 +95,7 @@ def get_extensions(): sources=['mkl/_mklinitmodule.c'], define_macros=defs, include_dirs=mkl_include_dirs, - libraries=mkl_libraries, + libraries=mkl_libraries + ["pthread"], library_dirs=mkl_library_dirs, extra_compile_args=[ '-DNDEBUG' @@ -155,7 +151,7 @@ def setup_package(): test_suite='nose.collector', python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', setup_requires=['setuptools', 'cython'], - install_requires=['six'], + install_requires=[], packages=setuptools.find_packages(), ext_modules=get_extensions() ) From bbb3361c85e9b397bbf4aeb0b5272f293e28a9db Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Sun, 23 May 2021 22:37:38 -0500 Subject: [PATCH 3/4] Replaced use of six.integer_types with numbers.Integral Added Cython directives for language_level=2 --- mkl/_mkl_service.pyx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mkl/_mkl_service.pyx b/mkl/_mkl_service.pyx index f500968..ab38fe7 100644 --- a/mkl/_mkl_service.pyx +++ b/mkl/_mkl_service.pyx @@ -23,10 +23,12 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# distutils: language = c +# cython: language_level=3 -import six +import numbers import warnings -cimport _mkl_service as mkl +cimport mkl._mkl_service as mkl ctypedef struct MemStatData: @@ -80,9 +82,9 @@ cdef int __domain_to_mkl_domain(domain): 'pardiso': mkl.MKL_DOMAIN_PARDISO, 'all': mkl.MKL_DOMAIN_ALL } - if isinstance(domain, six.integer_types): - c_mkl_domain = domain - elif isinstance(domain, six.string_types): + if isinstance(domain, numbers.Integral): + c_mkl_domain = domain + elif isinstance(domain, str): if domain not in _mapping: c_mkl_domain = __warn_and_fallback_on_default_domain(domain) else: @@ -113,7 +115,7 @@ cpdef set_num_threads_local(num_threads): https://software.intel.com/en-us/mkl-developer-reference-c-mkl-set-num-threads-local """ cdef c_num_threads = 0 - if isinstance(num_threads, six.string_types): + if isinstance(num_threads, str): if num_threads is not 'global_num_threads': raise ValueError("The argument of set_num_threads_local is expected " "to be a non-negative integer or a string 'global_num_threads'") @@ -382,9 +384,9 @@ cdef __mkl_status_to_string(int mkl_status): cdef int __python_obj_to_int(obj, func_name): - if not isinstance(obj, six.integer_types): + if not isinstance(obj, numbers.Integral): raise ValueError("The argument of " + func_name + " is expected to be a positive integer") - cdef c_int = obj + cdef int c_int = obj return c_int @@ -772,7 +774,7 @@ cdef object __enable_instructions(isa=None): cdef int c_mkl_isa = __mkl_str_to_int(isa, __variables['input']) cdef int c_mkl_status = mkl.mkl_enable_instructions(c_mkl_isa) - + return __mkl_status_to_string(c_mkl_status) From 0c3f7e060ff8f9216280752d0ac98f7e7e15c505 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Tue, 25 May 2021 07:10:29 -0500 Subject: [PATCH 4/4] fixed tabulations --- mkl/_mklinitmodule.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mkl/_mklinitmodule.c b/mkl/_mklinitmodule.c index 38a3317..791cfb6 100644 --- a/mkl/_mklinitmodule.c +++ b/mkl/_mklinitmodule.c @@ -39,28 +39,29 @@ static const char* verbose; #if FORCE_PRELOADING #define VERBOSE(...) if(verbose) printf("mkl-service + Intel(R) MKL: " __VA_ARGS__) + static void restore_mtlayer(void) { if (mtlayer) { - VERBOSE("Re-setting Intel(R) MKL_THREADING_LAYER=%s for the forked process\n", mtlayer); \ - setenv("MKL_THREADING_LAYER", mtlayer, 1); + VERBOSE("Re-setting Intel(R) MKL_THREADING_LAYER=%s for the forked process\n", mtlayer); + setenv("MKL_THREADING_LAYER", mtlayer, 1); } else { - VERBOSE("Unsetting Intel(R) MKL_THREADING_LAYER variable for the forked process \n"); \ - unsetenv("MKL_THREADING_LAYER"); + VERBOSE("Unsetting Intel(R) MKL_THREADING_LAYER variable for the forked process \n"); + unsetenv("MKL_THREADING_LAYER"); } } #endif static void _preload_threading_layer(void) { #if FORCE_PRELOADING -#define SET_MTLAYER(L) do { \ +#define SET_MTLAYER(L) do { \ VERBOSE("setting Intel(R) MKL to use " #L " OpenMP runtime\n"); \ - mkl_set_threading_layer(MKL_THREADING_##L); \ - setenv("MKL_THREADING_LAYER", #L, 0); \ - pthread_atfork(NULL, NULL, &restore_mtlayer); \ + mkl_set_threading_layer(MKL_THREADING_##L); \ + setenv("MKL_THREADING_LAYER", #L, 0); \ + pthread_atfork(NULL, NULL, &restore_mtlayer); \ } while(0) -#define PRELOAD(lib) do { \ - VERBOSE("preloading %s runtime\n", lib); \ - dlopen(lib, RTLD_LAZY|RTLD_GLOBAL); \ +#define PRELOAD(lib) do { \ + VERBOSE("preloading %s runtime\n", lib); \ + dlopen(lib, RTLD_LAZY|RTLD_GLOBAL); \ } while(0) /* * The following is the pseudo-code skeleton for reinterpreting unset MKL_THREADING_LAYER