diff --git a/CHANGES.rst b/CHANGES.rst index d242b47..4a6cf84 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -49,3 +49,9 @@ Closed issues #8, #7 and #5. Extended `mkl.cbwr_set` to recognize `'avx512_e1'`, `'avx512_mic_e1'`, as as strict conditional numerical reproducibility, supported via `'avx2,strict'`, `'avx512,strict'` (see [issue/8](http://github.com/IntelPython/mkl-service/issues/8)). Extended `mkl.cbwrt_get()` to mean `mkl.cbwr('all')`. + +2.3.0 +===== + +Fixed CI to actually execute tests. Populated CBWR constants to match MKL headers. +Added tests checking that `cbwr_set` and `cbwr_get` round-trip. diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 8c2996f..b3ab53f 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -1,4 +1,4 @@ -{% set version = "2.1.0" %} +{% set version = "2.3.0" %} {% set buildnumber = 0 %} package: @@ -20,20 +20,22 @@ requirements: host: - python - setuptools - - mkl-devel + - mkl-devel >=2019.3 - cython run: - python - - mkl + - mkl >=2019.3 - six test: - commands: - - nosetests -v mkl requires: - nose imports: - mkl + commands: + - nosetests -v tests + source_files: + - tests about: home: http://github.com/IntelPython/mkl-service diff --git a/mkl/_mkl_service.pxd b/mkl/_mkl_service.pxd index 0c40d21..819e5c6 100644 --- a/mkl/_mkl_service.pxd +++ b/mkl/_mkl_service.pxd @@ -45,10 +45,16 @@ cdef extern from "mkl.h": int MKL_MEM_MCDRAM # CNR Control Constants + int MKL_CBWR_BRANCH + int MKL_CBWR_ALL + + int MKL_CBWR_STRICT + + int MKL_CBWR_OFF + int MKL_CBWR_BRANCH_OFF int MKL_CBWR_AUTO int MKL_CBWR_COMPATIBLE int MKL_CBWR_SSE2 - int MKL_CBWR_SSE3 int MKL_CBWR_SSSE3 int MKL_CBWR_SSE4_1 int MKL_CBWR_SSE4_2 @@ -56,15 +62,14 @@ cdef extern from "mkl.h": int MKL_CBWR_AVX2 int MKL_CBWR_AVX512_MIC int MKL_CBWR_AVX512 - int MKL_CBWR_STRICT - int MKL_CBWR_AVX512_E1 int MKL_CBWR_AVX512_MIC_E1 - int MKL_CBWR_BRANCH - int MKL_CBWR_ALL + int MKL_CBWR_AVX512_E1 + int MKL_CBWR_SUCCESS - int MKL_CBWR_BRANCH_OFF + int MKL_CBWR_ERR_INVALID_SETTINGS int MKL_CBWR_ERR_INVALID_INPUT int MKL_CBWR_ERR_UNSUPPORTED_BRANCH + int MKL_CBWR_ERR_UNKNOWN_BRANCH int MKL_CBWR_ERR_MODE_CHANGE_FAILURE # ISA Constants diff --git a/mkl/_mkl_service.pyx b/mkl/_mkl_service.pyx index eed1c3b..b375fd6 100644 --- a/mkl/_mkl_service.pyx +++ b/mkl/_mkl_service.pyx @@ -645,23 +645,23 @@ cdef object __cbwr_set(branch=None): """ __variables = { 'input': { - 'off': mkl.MKL_CBWR_BRANCH_OFF, + 'off': mkl.MKL_CBWR_OFF, + 'branch_off': mkl.MKL_CBWR_BRANCH_OFF, 'auto': mkl.MKL_CBWR_AUTO, 'compatible': mkl.MKL_CBWR_COMPATIBLE, 'sse2': mkl.MKL_CBWR_SSE2, - 'sse3': mkl.MKL_CBWR_SSE3, 'ssse3': mkl.MKL_CBWR_SSSE3, 'sse4_1': mkl.MKL_CBWR_SSE4_1, 'sse4_2': mkl.MKL_CBWR_SSE4_2, 'avx': mkl.MKL_CBWR_AVX, 'avx2': mkl.MKL_CBWR_AVX2, - 'avx512_mic': mkl.MKL_CBWR_AVX512_MIC, - 'avx512': mkl.MKL_CBWR_AVX512, - 'avx512_e1': mkl.MKL_CBWR_AVX512_E1, - 'avx512_mic_e1': mkl.MKL_CBWR_AVX512_MIC_E1, 'avx2,strict': mkl.MKL_CBWR_AVX2 | mkl.MKL_CBWR_STRICT, + 'avx512_mic': mkl.MKL_CBWR_AVX512_MIC, 'avx512_mic,strict': mkl.MKL_CBWR_AVX512_MIC | mkl.MKL_CBWR_STRICT, + 'avx512': mkl.MKL_CBWR_AVX512, 'avx512,strict': mkl.MKL_CBWR_AVX512 | mkl.MKL_CBWR_STRICT, + 'avx512_mic_e1': mkl.MKL_CBWR_AVX512_MIC_E1, + 'avx512_e1': mkl.MKL_CBWR_AVX512_E1, 'avx512_e1,strict': mkl.MKL_CBWR_AVX512_E1 | mkl.MKL_CBWR_STRICT, }, 'output': { @@ -690,19 +690,23 @@ cdef inline __cbwr_get(cnr_const=None): 'all': mkl.MKL_CBWR_ALL, }, 'output': { - mkl.MKL_CBWR_BRANCH_OFF: 'off', + mkl.MKL_CBWR_BRANCH_OFF: 'branch_off', mkl.MKL_CBWR_AUTO: 'auto', mkl.MKL_CBWR_COMPATIBLE: 'compatible', mkl.MKL_CBWR_SSE2: 'sse2', - mkl.MKL_CBWR_SSE3: 'sse3', mkl.MKL_CBWR_SSSE3: 'ssse3', mkl.MKL_CBWR_SSE4_1: 'sse4_1', mkl.MKL_CBWR_SSE4_2: 'sse4_2', mkl.MKL_CBWR_AVX: 'avx', mkl.MKL_CBWR_AVX2: 'avx2', + mkl.MKL_CBWR_AVX2 | mkl.MKL_CBWR_STRICT: 'avx2,strict', mkl.MKL_CBWR_AVX512_MIC: 'avx512_mic', + mkl.MKL_CBWR_AVX512_MIC | mkl.MKL_CBWR_STRICT: 'avx512_mic,strict', mkl.MKL_CBWR_AVX512: 'avx512', - mkl.MKL_CBWR_SUCCESS: 'success', + mkl.MKL_CBWR_AVX512 | mkl.MKL_CBWR_STRICT: 'avx512,strict', + mkl.MKL_CBWR_AVX512_MIC_E1: 'avx512_mic_e1', + mkl.MKL_CBWR_AVX512_E1: 'avx512_e1', + mkl.MKL_CBWR_AVX512_E1 | mkl.MKL_CBWR_STRICT: 'avx512_e1,strict', mkl.MKL_CBWR_ERR_INVALID_INPUT: 'err_invalid_input', }, } @@ -721,17 +725,25 @@ cdef object __cbwr_get_auto_branch(): """ __variables = { 'output': { + mkl.MKL_CBWR_BRANCH_OFF: 'branch_off', mkl.MKL_CBWR_AUTO: 'auto', mkl.MKL_CBWR_COMPATIBLE: 'compatible', mkl.MKL_CBWR_SSE2: 'sse2', - mkl.MKL_CBWR_SSE3: 'sse3', mkl.MKL_CBWR_SSSE3: 'ssse3', mkl.MKL_CBWR_SSE4_1: 'sse4_1', mkl.MKL_CBWR_SSE4_2: 'sse4_2', mkl.MKL_CBWR_AVX: 'avx', mkl.MKL_CBWR_AVX2: 'avx2', + mkl.MKL_CBWR_AVX2 | mkl.MKL_CBWR_STRICT: 'avx2,strict', mkl.MKL_CBWR_AVX512_MIC: 'avx512_mic', + mkl.MKL_CBWR_AVX512_MIC | mkl.MKL_CBWR_STRICT: 'avx512_mic,strict', mkl.MKL_CBWR_AVX512: 'avx512', + mkl.MKL_CBWR_AVX512 | mkl.MKL_CBWR_STRICT: 'avx512,strict', + mkl.MKL_CBWR_AVX512_MIC_E1: 'avx512_mic_e1', + mkl.MKL_CBWR_AVX512_E1: 'avx512_e1', + mkl.MKL_CBWR_AVX512_E1 | mkl.MKL_CBWR_STRICT: 'avx512_e1,strict', + mkl.MKL_CBWR_SUCCESS: 'success', + mkl.MKL_CBWR_ERR_INVALID_INPUT: 'err_invalid_input', }, } diff --git a/tests/test_mkl_service.py b/tests/test_mkl_service.py index c83c159..8c9d2b4 100644 --- a/tests/test_mkl_service.py +++ b/tests/test_mkl_service.py @@ -24,7 +24,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from nose.tools import nottest +from nose.tools import assert_equals, nottest import six import mkl @@ -131,7 +131,7 @@ def test_get_dynamic(self): mkl.get_dynamic() -class test_timing: +class test_timing(): # https://software.intel.com/en-us/mkl-developer-reference-c-timing def test_second(self): s1 = mkl.second() @@ -191,49 +191,46 @@ def test_set_memory_limit(self): mkl.set_memory_limit(128) -class test_conditional_numerical_reproducibility_control: +class test_cnr_control(): # https://software.intel.com/en-us/mkl-developer-reference-c-conditional-numerical-reproducibility-control - def test_cbwr_set_off(self): - mkl.cbwr_set(branch='off') - - def test_cbwr_set_auto(self): - mkl.cbwr_set(branch='auto') - - def test_cbwr_set_compatible(self): - mkl.cbwr_set(branch='compatible') - - def test_cbwr_set_sse2(self): - mkl.cbwr_set(branch='sse2') - - def test_cbwr_set_sse3(self): - mkl.cbwr_set(branch='sse3') - - def test_cbwr_set_ssse3(self): - mkl.cbwr_set(branch='ssse3') - - def test_cbwr_set_sse4_1(self): - mkl.cbwr_set(branch='sse4_1') - - def test_cbwr_set_sse4_2(self): - mkl.cbwr_set(branch='sse4_2') - - def test_cbwr_set_avx(self): - mkl.cbwr_set(branch='avx') - - def test_cbwr_set_avx2(self): - mkl.cbwr_set(branch='avx2') - - def test_cbwr_set_avx512_mic(self): - mkl.cbwr_set(branch='avx512_mic') - - def test_cbwr_set_avx512(self): - mkl.cbwr_set(branch='avx512') - - def test_cbwr_get(self): - mkl.cbwr_get(cnr_const='all') - - def test_cbwr_get(self): - mkl.cbwr_get(cnr_const='branch') + def test_cbwr(self): + branches = [ + 'off', + 'branch_off', + 'auto', + 'compatible', + 'sse2', + 'ssse3', + 'sse4_1', + 'sse4_2', + 'avx', + 'avx2', + 'avx512_mic', + 'avx512', + 'avx512_mic_e1', + 'avx512_e1', + ] + strict = [ + 'avx2,strict', + 'avx512_mic,strict', + 'avx512,strict', + 'avx512_e1,strict', + ] + for branch in branches: + yield self.check_cbwr, branch, 'branch' + for branch in branches + strict: + yield self.check_cbwr, branch, 'all' + + def check_cbwr(self, 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_equals(actual_value, + expected_value, + msg="Round-trip failure for CNR branch '{}', CNR const '{}'".format(branch, cnr_const)) + elif status != 'err_unsupported_branch': + raise AssertionError(status) def test_cbwr_get_auto_branch(self): mkl.cbwr_get_auto_branch()