From 18c0627244c2a7354f5e5ef82a0ef26af9939a23 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Mon, 12 Feb 2024 10:03:27 -0600 Subject: [PATCH 1/2] Added except/noexcept annotations to cdef functions --- mkl/_mkl_service.pyx | 80 ++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/mkl/_mkl_service.pyx b/mkl/_mkl_service.pyx index feec20a..b40f5c5 100644 --- a/mkl/_mkl_service.pyx +++ b/mkl/_mkl_service.pyx @@ -391,33 +391,33 @@ cpdef vml_clear_err_status(): return __vml_clear_err_status() -cdef __mkl_status_to_string(int mkl_status): +cdef str __mkl_status_to_string(int mkl_status) noexcept: if mkl_status == 1: return 'success' else: return 'error' -cdef int __python_obj_to_int(obj, func_name): +cdef int __python_obj_to_int(obj, func_name) except *: if not isinstance(obj, numbers.Integral): raise ValueError("The argument of " + func_name + " is expected to be a positive integer") cdef int c_int = obj return c_int -cdef void __check_positive_num_threads(int p, func_name): +cdef void __check_positive_num_threads(int p, func_name) except *: if p <= 0: warnings.warn("Non-positive argument of " + func_name + " is being ignored, number of threads will not be changed") -cdef void __check_non_negative_num_threads(int p, func_name): +cdef void __check_non_negative_num_threads(int p, func_name) except *: if p < 0: warnings.warn("Negative argument of " + func_name + " is being ignored, number of threads will not be changed") -cdef inline int __mkl_str_to_int(variable, possible_variables_dict): +cdef inline int __mkl_str_to_int(variable, possible_variables_dict) except *: if variable is None: raise ValueError("Variable can not be None") if possible_variables_dict is None: @@ -429,7 +429,7 @@ cdef inline int __mkl_str_to_int(variable, possible_variables_dict): return possible_variables_dict[variable] -cdef __mkl_int_to_str(int mkl_int_variable, possible_variables_dict): +cdef __mkl_int_to_str(int mkl_int_variable, possible_variables_dict) except *: if possible_variables_dict is None: raise RuntimeError("Dictionary mapping possible internal code to output string is missing") @@ -441,7 +441,7 @@ cdef __mkl_int_to_str(int mkl_int_variable, possible_variables_dict): # Version Information -cdef inline mkl.MKLVersion __get_version(): +cdef mkl.MKLVersion __get_version() noexcept: """ Returns the Intel(R) MKL version. """ @@ -450,7 +450,7 @@ cdef inline mkl.MKLVersion __get_version(): return c_mkl_version -cdef __get_version_string(): +cdef str __get_version_string() except *: """ Returns the Intel(R) MKL version in a character string. """ @@ -461,7 +461,7 @@ cdef __get_version_string(): # Threading -cdef inline int __set_num_threads(int num_threads): +cdef inline int __set_num_threads(int num_threads) noexcept: """ Specifies the number of OpenMP* threads to use. """ @@ -471,7 +471,7 @@ cdef inline int __set_num_threads(int num_threads): return prev_num_threads -cdef inline int __domain_set_num_threads(int c_num_threads, int mkl_domain): +cdef inline int __domain_set_num_threads(int c_num_threads, int mkl_domain) noexcept: """ Specifies the number of OpenMP* threads for a particular function domain. """ @@ -479,7 +479,7 @@ cdef inline int __domain_set_num_threads(int c_num_threads, int mkl_domain): return mkl_status -cdef inline int __set_num_threads_local(int c_num_threads): +cdef inline int __set_num_threads_local(int c_num_threads) noexcept: """ Specifies the number of OpenMP* threads for all Intel(R) MKL functions on the current execution thread. """ @@ -488,7 +488,7 @@ cdef inline int __set_num_threads_local(int c_num_threads): return c_mkl_status -cdef inline int __set_dynamic(int c_enable): +cdef inline int __set_dynamic(int c_enable) noexcept: """ Enables Intel(R) MKL to dynamically change the number of OpenMP* threads. """ @@ -497,14 +497,14 @@ cdef inline int __set_dynamic(int c_enable): return __get_max_threads() -cdef inline int __get_max_threads(): +cdef inline int __get_max_threads() noexcept: """ Gets the number of OpenMP* threads targeted for parallelism. """ return mkl.mkl_get_max_threads() -cdef inline int __domain_get_max_threads(int c_mkl_domain): +cdef inline int __domain_get_max_threads(int c_mkl_domain) noexcept: """ Gets the number of OpenMP* threads targeted for parallelism for a particular function domain. """ @@ -513,7 +513,7 @@ cdef inline int __domain_get_max_threads(int c_mkl_domain): return c_num_threads -cdef inline int __get_dynamic(): +cdef inline int __get_dynamic() noexcept: """ Determines whether Intel(R) MKL is enabled to dynamically change the number of OpenMP* threads. """ @@ -521,7 +521,7 @@ cdef inline int __get_dynamic(): # Timing -cdef inline float __second(): +cdef inline float __second() noexcept: """ Returns elapsed time in seconds. Use to estimate real time between two calls to this function. @@ -530,7 +530,7 @@ cdef inline float __second(): return mkl.second() -cdef inline double __dsecnd(): +cdef inline double __dsecnd() noexcept: """ Returns elapsed time in seconds. Use to estimate real time between two calls to this function. @@ -539,7 +539,7 @@ cdef inline double __dsecnd(): return mkl.dsecnd() -cdef inline mkl.MKL_UINT64 __get_cpu_clocks(): +cdef inline mkl.MKL_UINT64 __get_cpu_clocks() noexcept: """ Returns elapsed CPU clocks. """ @@ -548,21 +548,21 @@ cdef inline mkl.MKL_UINT64 __get_cpu_clocks(): return clocks -cdef inline double __get_cpu_frequency(): +cdef inline double __get_cpu_frequency() noexcept: """ Returns the current CPU frequency value in GHz. """ return mkl.mkl_get_cpu_frequency() -cdef inline double __get_max_cpu_frequency(): +cdef inline double __get_max_cpu_frequency() noexcept: """ Returns the maximum CPU frequency value in GHz. """ return mkl.mkl_get_max_cpu_frequency() -cdef inline double __get_clocks_frequency(): +cdef inline double __get_clocks_frequency() noexcept: """ Returns the frequency value in GHz based on constant-rate Time Stamp Counter. """ @@ -570,7 +570,7 @@ cdef inline double __get_clocks_frequency(): # Memory Management. See the Intel(R) MKL Developer Guide for more memory usage information. -cdef inline void __free_buffers(): +cdef inline void __free_buffers() noexcept: """ Frees unused memory allocated by the Intel(R) MKL Memory Allocator. """ @@ -578,7 +578,7 @@ cdef inline void __free_buffers(): return -cdef inline void __thread_free_buffers(): +cdef inline void __thread_free_buffers() noexcept: """ Frees unused memory allocated by the Intel(R) MKL Memory Allocator in the current thread. """ @@ -586,14 +586,14 @@ cdef inline void __thread_free_buffers(): return -cdef inline int __disable_fast_mm(): +cdef inline int __disable_fast_mm() noexcept: """ Turns off the Intel(R) MKL Memory Allocator for Intel(R) MKL functions to directly use the system malloc/free functions. """ return mkl.mkl_disable_fast_mm() -cdef inline MemStatData __mem_stat(): +cdef inline MemStatData __mem_stat() noexcept: """ Reports the status of the Intel(R) MKL Memory Allocator. """ @@ -602,7 +602,7 @@ cdef inline MemStatData __mem_stat(): return mem_stat_data -cdef object __peak_mem_usage(mem_const): +cdef object __peak_mem_usage(mem_const) except *: """ Reports the peak memory allocated by the Intel(R) MKL Memory Allocator. """ @@ -625,7 +625,7 @@ cdef object __peak_mem_usage(mem_const): return memory_allocator -cdef inline object __set_memory_limit(limit): +cdef inline object __set_memory_limit(limit) except *: """ On Linux, sets the limit of memory that Intel(R) MKL can allocate for a specified type of memory. """ @@ -636,7 +636,7 @@ cdef inline object __set_memory_limit(limit): # Conditional Numerical Reproducibility -cdef object __cbwr_set(branch=None): +cdef object __cbwr_set(branch=None) except *: """ Configures the CNR mode of Intel(R) MKL. """ @@ -676,7 +676,7 @@ cdef object __cbwr_set(branch=None): return status -cdef inline __cbwr_get(cnr_const=None): +cdef inline __cbwr_get(cnr_const=None) except *: """ Returns the current CNR settings. """ @@ -714,7 +714,7 @@ cdef inline __cbwr_get(cnr_const=None): return status -cdef object __cbwr_get_auto_branch(): +cdef object __cbwr_get_auto_branch() except *: """ Automatically detects the CNR code branch for your platform. """ @@ -749,7 +749,7 @@ cdef object __cbwr_get_auto_branch(): # Miscellaneous -cdef object __enable_instructions(isa=None): +cdef object __enable_instructions(isa=None) except *: """ Enables dispatching for new Intel architectures or restricts the set of Intel instruction sets available for dispatching. """ @@ -776,7 +776,7 @@ cdef object __enable_instructions(isa=None): return __mkl_status_to_string(c_mkl_status) -cdef object __set_env_mode(): +cdef object __set_env_mode() except *: """ Sets up the mode that ignores environment settings specific to Intel(R) MKL. See mkl_set_env_mode(1). """ @@ -793,7 +793,7 @@ cdef object __set_env_mode(): return status -cdef object __get_env_mode(): +cdef object __get_env_mode() except *: """ Query the current environment mode. See mkl_set_env_mode(0). """ @@ -809,14 +809,14 @@ cdef object __get_env_mode(): return status -cdef inline int __verbose(int c_enable): +cdef inline int __verbose(int c_enable) noexcept: """ Enables or disables Intel(R) MKL Verbose mode. """ return mkl.mkl_verbose(c_enable) -cdef __set_mpi(vendor, custom_library_name=None): +cdef __set_mpi(vendor, custom_library_name=None) except *: """ Sets the implementation of the message-passing interface to be used by Intel(R) MKL. """ @@ -854,7 +854,7 @@ cdef __set_mpi(vendor, custom_library_name=None): # VM Service Functions -cdef object __vml_set_mode(accuracy, ftzdaz, errmode): +cdef object __vml_set_mode(accuracy, ftzdaz, errmode) except *: """ Sets a new mode for VM functions according to the mode parameter and stores the previous VM mode to oldmode. """ @@ -919,7 +919,7 @@ cdef object __vml_set_mode(accuracy, ftzdaz, errmode): return (accuracy, ftzdaz, errmode) -cdef object __vml_get_mode(): +cdef object __vml_get_mode() except *: """ Gets the VM mode. """ @@ -972,7 +972,7 @@ __mkl_vml_status = { } -cdef object __vml_set_err_status(status): +cdef object __vml_set_err_status(status) except *: """ Sets the new VM Error Status according to err and stores the previous VM Error Status to olderr. """ @@ -1006,7 +1006,7 @@ cdef object __vml_set_err_status(status): return status -cdef object __vml_get_err_status(): +cdef object __vml_get_err_status() except *: """ Gets the VM Error Status. """ @@ -1030,7 +1030,7 @@ cdef object __vml_get_err_status(): return status -cdef object __vml_clear_err_status(): +cdef object __vml_clear_err_status() except *: """ Sets the VM Error Status to VML_STATUS_OK and stores the previous VM Error Status to olderr. """ From 204c059ad67f6495d36be291aa876a41cd9f89cc Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Mon, 12 Feb 2024 10:06:29 -0600 Subject: [PATCH 2/2] Linter changes, update copyright year Moved test_get_version and test_get_version_string to the end of the test file with comment for why. Expanded return statuses from cbwr_set which we do not consider test failure, with comment added. --- mkl/__init__.py | 2 +- mkl/_mkl_service.pxd | 2 +- mkl/_mkl_service.pyx | 2 +- mkl/tests/test_mkl_service.py | 125 +++++++++++++++++++++++++++------- setup.py | 2 +- 5 files changed, 103 insertions(+), 30 deletions(-) diff --git a/mkl/__init__.py b/mkl/__init__.py index 59d7f59..3de3342 100644 --- a/mkl/__init__.py +++ b/mkl/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018-2019, Intel Corporation +# Copyright (c) 2018-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: diff --git a/mkl/_mkl_service.pxd b/mkl/_mkl_service.pxd index e11f659..f48c3cb 100644 --- a/mkl/_mkl_service.pxd +++ b/mkl/_mkl_service.pxd @@ -1,4 +1,4 @@ -# Copyright (c) 2018-2019, Intel Corporation +# Copyright (c) 2018-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: diff --git a/mkl/_mkl_service.pyx b/mkl/_mkl_service.pyx index b40f5c5..8127ef6 100644 --- a/mkl/_mkl_service.pyx +++ b/mkl/_mkl_service.pyx @@ -1,4 +1,4 @@ -# Copyright (c) 2018-2019, Intel Corporation +# Copyright (c) 2018-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: diff --git a/mkl/tests/test_mkl_service.py b/mkl/tests/test_mkl_service.py index 54829d1..3822a82 100644 --- a/mkl/tests/test_mkl_service.py +++ b/mkl/tests/test_mkl_service.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018-2019, Intel Corporation +# Copyright (c) 2018-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -28,27 +28,14 @@ import mkl -def test_get_version(): - v = mkl.get_version() - assert isinstance(v, dict) - assert 'MajorVersion' in v - assert 'MinorVersion' in v - assert 'UpdateVersion' in v - - -def test_get_version_string(): - v = mkl.get_version_string() - assert isinstance(v, str) - assert 'Math Kernel Library' in v - - def test_set_num_threads(): saved = mkl.get_max_threads() - half_nt = int( (1 + saved) / 2 ) + half_nt = int( (1 + saved) / 2 ) mkl.set_num_threads(half_nt) assert mkl.get_max_threads() == half_nt mkl.set_num_threads(saved) + def test_domain_set_num_threads_blas(): saved_blas_nt = mkl.domain_get_max_threads(domain='blas') saved_fft_nt = mkl.domain_get_max_threads(domain='fft') @@ -75,22 +62,27 @@ def test_domain_set_num_threads_blas(): status = mkl.domain_set_num_threads(saved_vml_nt, domain='vml') assert status == 'success' + def test_domain_set_num_threads_fft(): status = mkl.domain_set_num_threads(4, domain='fft') assert status == 'success' + def test_domain_set_num_threads_vml(): status = mkl.domain_set_num_threads(4, domain='vml') assert status == 'success' + def test_domain_set_num_threads_pardiso(): status = mkl.domain_set_num_threads(4, domain='pardiso') assert status == 'success' + def test_domain_set_num_threads_all(): status = mkl.domain_set_num_threads(4, domain='all') assert status == 'success' + def test_set_num_threads_local(): mkl.set_num_threads(1) status = mkl.set_num_threads_local(2) @@ -102,27 +94,35 @@ def test_set_num_threads_local(): status = mkl.set_num_threads_local(8) assert status == 'global_num_threads' + def test_set_dynamic(): mkl.set_dynamic(True) + def test_get_max_threads(): mkl.get_max_threads() + def test_domain_get_max_threads_blas(): mkl.domain_get_max_threads(domain='blas') + def test_domain_get_max_threads_fft(): mkl.domain_get_max_threads(domain='fft') + def test_domain_get_max_threads_vml(): mkl.domain_get_max_threads(domain='vml') + def test_domain_get_max_threads_pardiso(): mkl.domain_get_max_threads(domain='pardiso') + def test_domain_get_max_threads_all(): mkl.domain_get_max_threads(domain='all') + def test_get_dynamic(): mkl.get_dynamic() @@ -134,24 +134,29 @@ def test_second(): delta = s2 - s1 assert delta >= 0 + def test_dsecnd(): d1 = mkl.dsecnd() d2 = mkl.dsecnd() delta = d2 - d1 assert delta >= 0 + def test_get_cpu_clocks(): c1 = mkl.get_cpu_clocks() c2 = mkl.get_cpu_clocks() delta = c2 - c1 assert delta >= 0 + def test_get_cpu_frequency(): assert mkl.get_cpu_frequency() >= 0 + def test_get_max_cpu_frequency(): assert mkl.get_max_cpu_frequency() >= 0 + def test_get_clocks_frequency(): assert mkl.get_clocks_frequency() >= 0 @@ -159,29 +164,50 @@ def test_get_clocks_frequency(): def test_free_buffers(): mkl.free_buffers() + def test_thread_free_buffers(): mkl.thread_free_buffers() + def test_disable_fast_mm(): mkl.disable_fast_mm() + def test_mem_stat(): mkl.mem_stat() + def test_peak_mem_usage_enable(): mkl.peak_mem_usage('enable') + def test_peak_mem_usage_disable(): mkl.peak_mem_usage('disable') + def test_peak_mem_usage_peak_mem(): mkl.peak_mem_usage('peak_mem') + def test_peak_mem_usage_peak_mem_reset(): mkl.peak_mem_usage('peak_mem_reset') + def test_set_memory_limit(): - mkl.set_memory_limit(128) + mkl.set_memory_limit(2**16) + + +def check_cbwr(branch, cnr_const): + status = mkl.cbwr_set(branch=branch) + if status == 'success': + expected_value = 'branch_off' if branch == 'off' else branch + actual_value = mkl.cbwr_get(cnr_const=cnr_const) + assert actual_value == expected_value, \ + f"Round-trip failure for CNR branch '{branch}', CNR const '{cnr_const}" + elif status not in ['err_unsupported_branch', 'err_mode_change_failure']: + # if MKL has been initialized already, + # setting CBWR will error with mode_change_failure + pytest.fail(status) branches = [ @@ -200,29 +226,25 @@ def test_set_memory_limit(): 'avx512_mic_e1', 'avx512_e1', ] + + strict = [ 'avx2,strict', 'avx512_mic,strict', 'avx512,strict', 'avx512_e1,strict', ] + + @pytest.mark.parametrize('branch', branches) def test_cbwr_branch(branch): check_cbwr(branch, 'branch') + @pytest.mark.parametrize('branch', branches + strict) def test_cbwr_all(branch): check_cbwr(branch, 'all') -def check_cbwr(branch, cnr_const): - status = mkl.cbwr_set(branch=branch) - if status == 'success': - expected_value = 'branch_off' if branch == 'off' else branch - actual_value = mkl.cbwr_get(cnr_const=cnr_const) - assert actual_value == expected_value, \ - f"Round-trip failure for CNR branch '{branch}', CNR const '{cnr_const}" - elif status != 'err_unsupported_branch': - pytest.fail(status) def test_cbwr_get_auto_branch(): mkl.cbwr_get_auto_branch() @@ -231,45 +253,58 @@ def test_cbwr_get_auto_branch(): def test_enable_instructions_avx512_mic_e1(): mkl.enable_instructions('avx512_mic_e1') + def test_enable_instructions_avx512(): mkl.enable_instructions('avx512') + def test_enable_instructions_avx512_mic(): mkl.enable_instructions('avx512_mic') + def test_enable_instructions_avx2(): mkl.enable_instructions('avx2') + def test_enable_instructions_avx(): mkl.enable_instructions('avx') + def test_enable_instructions_sse4_2(): mkl.enable_instructions('sse4_2') + def test_set_env_mode(): mkl.set_env_mode() + def test_get_env_mode(): mkl.get_env_mode() + def test_verbose_false(): mkl.verbose(False) + def test_verbose_true(): mkl.verbose(True) + @pytest.mark.skip(reason="Skipping MPI-related test") def test_set_mpi_custom(): mkl.set_mpi('custom', 'custom_library_name') + @pytest.mark.skip(reason="Skipping MPI-related test") def test_set_mpi_msmpi(): mkl.set_mpi('msmpi') + @pytest.mark.skip(reason="Skipping MPI-related test") def test_set_mpi_intelmpi(): mkl.set_mpi('intelmpi') + @pytest.mark.skip(reason="Skipping MPI-related test") def test_set_mpi_mpich2(): mkl.set_mpi('mpich2') @@ -279,53 +314,91 @@ def test_vml_set_get_mode_roundtrip(): saved = mkl.vml_get_mode() mkl.vml_set_mode(*saved) # should not raise errors + def test_vml_set_mode_ha_on_ignore(): mkl.vml_set_mode('ha', 'on', 'ignore') + def test_vml_set_mode_ha_on_errno(): mkl.vml_set_mode('ha', 'on', 'errno') + def test_vml_set_mode_la_on_stderr(): mkl.vml_set_mode('la', 'on', 'stderr') + def test_vml_set_mode_la_off_except(): mkl.vml_set_mode('la', 'off', 'except') + def test_vml_set_mode_op_off_callback(): mkl.vml_set_mode('ep', 'off', 'callback') + def test_vml_set_mode_ep_off_default(): mkl.vml_set_mode('ep', 'off', 'default') + def test_vml_get_mode(): mkl.vml_get_mode() + def test_vml_set_err_status_ok(): mkl.vml_set_err_status('ok') + def test_vml_set_err_status_accuracywarning(): mkl.vml_set_err_status('accuracywarning') + def test_vml_set_err_status_badsize(): mkl.vml_set_err_status('badsize') + def test_vml_set_err_status_badmem(): mkl.vml_set_err_status('badmem') + def test_vml_set_err_status_errdom(): mkl.vml_set_err_status('errdom') + def test_vml_set_err_status_sing(): mkl.vml_set_err_status('sing') + def test_vml_set_err_status_overflow(): mkl.vml_set_err_status('overflow') + def test_vml_set_err_status_underflow(): mkl.vml_set_err_status('underflow') + def test_vml_get_err_status(): mkl.vml_get_err_status() + def test_vml_clear_err_status(): mkl.vml_clear_err_status() + + +def test_get_version(): + """ + Version info sets mode of MKL library, such as + instruction pathways and conditional numerical + reproducibility regime. This test is moved to + the bottom to allow proper testing of functions + controllign those. + """ + v = mkl.get_version() + assert isinstance(v, dict) + assert 'MajorVersion' in v + assert 'MinorVersion' in v + assert 'UpdateVersion' in v + + +def test_get_version_string(): + v = mkl.get_version_string() + assert isinstance(v, str) + assert 'Math Kernel Library' in v diff --git a/setup.py b/setup.py index 3b63203..8016367 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2018-2019, Intel Corporation +# Copyright (c) 2018-2024, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: