From b84e22f7500e59f5a654de176e117cf990715ef7 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 12 Feb 2019 11:38:01 +0100 Subject: [PATCH 01/12] Refine runtime feature discovery python API and add documentation to Python API docs --- docs/api/python/index.md | 11 +++++ docs/api/python/libinfo/libinfo.md | 70 ++++++++++++++++++++++++++++++ python/mxnet/runtime.py | 12 ++++- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 docs/api/python/libinfo/libinfo.md diff --git a/docs/api/python/index.md b/docs/api/python/index.md index 6130078ee796..2e23b162ee77 100644 --- a/docs/api/python/index.md +++ b/docs/api/python/index.md @@ -174,6 +174,17 @@ Code examples are placed throughout the API documentation and these can be run a rtc/rtc.md ``` +## Run-Time Feature detection / Library Info + +```eval_rst +.. toctree:: + :maxdepth: 1 + + libinfo/libinfo.md +``` + + + ## Symbol API ```eval_rst diff --git a/docs/api/python/libinfo/libinfo.md b/docs/api/python/libinfo/libinfo.md new file mode 100644 index 000000000000..513a4aec7330 --- /dev/null +++ b/docs/api/python/libinfo/libinfo.md @@ -0,0 +1,70 @@ +# Run-Time Feature detection / Library info + +```eval_rst +.. currentmodule:: mxnet.runtime +``` + +## Overview + +The libinfo functionality allows to check for compile-time features supported by the library. + +### Example usage + +```python +In [1]: import mxnet as mx + +In [2]: import mxnet.runtime + +In [3]: mx.runtime.libinfo_features() +Out[3]: +[✔ CUDA, + ✔ CUDNN, + ✔ NCCL, + ✔ CUDA_RTC, + ✔ TENSORRT, + ✖ CPU_SSE, + ✖ CPU_SSE2, + ✖ CPU_SSE3, + ✖ CPU_SSE4_1, + ✖ CPU_SSE4_2, + ✔ CPU_SSE4A, + ✖ CPU_AVX, + ✔ CPU_AVX2, + ✔ OPENMP, + ✔ SSE, + ✖ F16C, + ✔ JEMALLOC, + ✖ BLAS_OPEN, + ✔ BLAS_ATLAS, + ✔ BLAS_MKL, + ✔ BLAS_APPLE, + ✔ LAPACK, + ✔ MKLDNN, + ✖ OPENCV, + ✔ CAFFE, + ✔ PROFILER, + ✔ DIST_KVSTORE, + ✔ CXX14, + ✔ SIGNAL_HANDLER, + ✖ DEBUG] +``` + + +```eval_rst +.. autosummary:: + :nosignatures: + + LibFeature + libinfo_features +``` + +## API Reference + + + +```eval_rst +.. automodule:: mxnet.runtime + :members: +``` + + diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index afb393281420..e1933125d37a 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -28,11 +28,21 @@ class LibFeature(ctypes.Structure): Compile time feature description """ _fields_ = [ - ("name", ctypes.c_char_p), + ("_name", ctypes.c_char_p), ("index", ctypes.c_uint32), ("enabled", ctypes.c_bool) ] + @property + def name(self): + return self._name.decode() + + def __repr__(self): + if self.enabled: + return "✔ {}".format(self.name) + else: + return "✖ {}".format(self.name) + def libinfo_features(): """ Check the library for compile-time features. The list of features are maintained in libinfo.h and libinfo.cc From 07c0ef02272a5a989776ef9c9171c59fe8ec9526 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 12 Feb 2019 15:53:54 +0100 Subject: [PATCH 02/12] Fix lint --- python/mxnet/runtime.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index e1933125d37a..3c2c88efb643 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. +# -*- coding: utf-8 -*- # coding: utf-8 # pylint: disable=not-an-iterable From b9b4fc922d848d5dc3f85ff77118dd519c8ca6f2 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 13 Feb 2019 00:36:38 +0100 Subject: [PATCH 03/12] Provide is_enabled method to check if feature is present from string --- python/mxnet/runtime.py | 19 ++++++++++++++++++- tests/python/unittest/test_runtime.py | 11 +++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index 3c2c88efb643..d9813a56a350 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -50,10 +50,27 @@ def libinfo_features(): Returns ------- - A list of class LibFeature indicating which features are available and enabled + :return: list of class LibFeature indicating which features are available and enabled """ lib_features = ctypes.POINTER(LibFeature)() lib_features_size = ctypes.c_size_t() check_call(_LIB.MXLibInfoFeatures(ctypes.byref(lib_features), ctypes.byref(lib_features_size))) feature_list = [lib_features[i] for i in range(lib_features_size.value)] return feature_list + +def is_enabled(tocheck): + """ + Check for a particular feature by name + + Parameters + ---------- + :param x: str The name of a valid feature as string for example 'CUDA' + + Returns + ------- + :return: bool True if it's enabled, False if it's disabled, RuntimeError if the feature is not known + """ + feature_dict = {f.name: f.enabled for f in libinfo_features()} + if tocheck not in feature_dict: + raise RuntimeError("Feature '{}' is unknown, known features are: {}".format(tocheck, list(feature_dict.keys()))) + return feature_dict[tocheck] diff --git a/tests/python/unittest/test_runtime.py b/tests/python/unittest/test_runtime.py index 433301819252..59f484e61e2e 100644 --- a/tests/python/unittest/test_runtime.py +++ b/tests/python/unittest/test_runtime.py @@ -29,6 +29,17 @@ def test_libinfo_features(): ok_(type(features) is list) ok_(len(features) > 0) +def test_is_enabled(): + features = libinfo_features() + for f in features: + if f.enabled: + ok_(is_enabled(f.name)) + else: + ok_(not is_enabled(f.name)) + +@raises(RuntimeError) +def test_is_enabled_not_existing(): + is_enabled('this girl is on fire') if __name__ == "__main__": From aa097c1c4c1eba642b888206e30db15f2d2196da Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 13 Feb 2019 00:38:40 +0100 Subject: [PATCH 04/12] Refine docs, add is_enabled --- docs/api/python/libinfo/libinfo.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/api/python/libinfo/libinfo.md b/docs/api/python/libinfo/libinfo.md index 513a4aec7330..ebea610eb273 100644 --- a/docs/api/python/libinfo/libinfo.md +++ b/docs/api/python/libinfo/libinfo.md @@ -15,8 +15,14 @@ In [1]: import mxnet as mx In [2]: import mxnet.runtime -In [3]: mx.runtime.libinfo_features() -Out[3]: +In [3]: mxnet.runtime.is_enabled('DEBUG') +Out[3]: True + +In [4]: mxnet.runtime.is_enabled('CUDA') +Out[4]: False + +In [5]: mx.runtime.libinfo_features() +Out[5]: [✔ CUDA, ✔ CUDNN, ✔ NCCL, From dcf6bd92d61bc70e9e06a6e805019b562806165a Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 13 Feb 2019 00:31:54 +0000 Subject: [PATCH 05/12] Fix encoding --- python/mxnet/runtime.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index d9813a56a350..4b9f2be1e235 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -1,3 +1,5 @@ +# coding: utf-8 + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -15,8 +17,6 @@ # specific language governing permissions and limitations # under the License. -# -*- coding: utf-8 -*- -# coding: utf-8 # pylint: disable=not-an-iterable """runtime querying of compile time features in the native library""" From 3927fc27e26d38402498da2ff1dc69ae72b4ee7b Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 13 Feb 2019 01:46:52 +0100 Subject: [PATCH 06/12] Fix doc --- docs/api/python/libinfo/libinfo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/python/libinfo/libinfo.md b/docs/api/python/libinfo/libinfo.md index ebea610eb273..d2d7db8b1755 100644 --- a/docs/api/python/libinfo/libinfo.md +++ b/docs/api/python/libinfo/libinfo.md @@ -10,7 +10,7 @@ The libinfo functionality allows to check for compile-time features supported by ### Example usage -```python +``` In [1]: import mxnet as mx In [2]: import mxnet.runtime From 1d93f7968d052a56572872806e295ed910d82079 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 14 Feb 2019 01:20:07 +0100 Subject: [PATCH 07/12] Address CR suggestions --- docs/api/python/libinfo/libinfo.md | 55 ++++++++------------------- python/mxnet/runtime.py | 49 +++++++++++++++--------- tests/python/unittest/test_runtime.py | 23 ++++++----- 3 files changed, 56 insertions(+), 71 deletions(-) diff --git a/docs/api/python/libinfo/libinfo.md b/docs/api/python/libinfo/libinfo.md index d2d7db8b1755..7b13d77ebedf 100644 --- a/docs/api/python/libinfo/libinfo.md +++ b/docs/api/python/libinfo/libinfo.md @@ -12,47 +12,22 @@ The libinfo functionality allows to check for compile-time features supported by ``` In [1]: import mxnet as mx + ...: import mxnet.runtime + ...: fs = mx.runtime.Features() -In [2]: import mxnet.runtime - -In [3]: mxnet.runtime.is_enabled('DEBUG') -Out[3]: True - -In [4]: mxnet.runtime.is_enabled('CUDA') -Out[4]: False - -In [5]: mx.runtime.libinfo_features() -Out[5]: -[✔ CUDA, - ✔ CUDNN, - ✔ NCCL, - ✔ CUDA_RTC, - ✔ TENSORRT, - ✖ CPU_SSE, - ✖ CPU_SSE2, - ✖ CPU_SSE3, - ✖ CPU_SSE4_1, - ✖ CPU_SSE4_2, - ✔ CPU_SSE4A, - ✖ CPU_AVX, - ✔ CPU_AVX2, - ✔ OPENMP, - ✔ SSE, - ✖ F16C, - ✔ JEMALLOC, - ✖ BLAS_OPEN, - ✔ BLAS_ATLAS, - ✔ BLAS_MKL, - ✔ BLAS_APPLE, - ✔ LAPACK, - ✔ MKLDNN, - ✖ OPENCV, - ✔ CAFFE, - ✔ PROFILER, - ✔ DIST_KVSTORE, - ✔ CXX14, - ✔ SIGNAL_HANDLER, - ✖ DEBUG] +In [2]: fs +Out[2]: [✖ CUDA, ✖ CUDNN, ✖ NCCL, ✖ CUDA_RTC, ✖ TENSORRT, ✔ CPU_SSE, ✔ CPU_SSE2, ✔ CPU_SSE3, ✔ CPU_SSE4_1, ✔ CPU_SSE4_2, ✖ CPU_SSE4A, ✔ CPU_AVX, ✖ CPU_AVX2, ✖ OPENMP, ✖ SSE, ✔ F16C, ✖ JEMALLOC, ✔ BLAS_OPEN, ✖ BLAS_ATLAS, ✖ BLAS_MKL, ✖ BLAS_APPLE, ✔ LAPACK, ✖ MKLDNN, ✔ OPENCV, ✖ CAFFE, ✖ PROFILER, ✖ DIST_KVSTORE, ✖ CXX14, ✔ SIGNAL_HANDLER, ✔ DEBUG] + +In [3]: fs['CUDA'].enabled +Out[3]: False + +In [4]: fs.is_enabled('CPU_SSE') +Out[4]: True + +In [5]: fs.is_enabled('CUDA') +Out[5]: False + +In [6]: ``` diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index 4b9f2be1e235..1fb0defba056 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -23,8 +23,9 @@ import ctypes from .base import _LIB, check_call +import collections -class LibFeature(ctypes.Structure): +class Feature(ctypes.Structure): """ Compile time feature description """ @@ -44,7 +45,7 @@ def __repr__(self): else: return "✖ {}".format(self.name) -def libinfo_features(): +def feature_list(): """ Check the library for compile-time features. The list of features are maintained in libinfo.h and libinfo.cc @@ -52,25 +53,35 @@ def libinfo_features(): ------- :return: list of class LibFeature indicating which features are available and enabled """ - lib_features = ctypes.POINTER(LibFeature)() + lib_features_c_array = ctypes.POINTER(Feature)() lib_features_size = ctypes.c_size_t() - check_call(_LIB.MXLibInfoFeatures(ctypes.byref(lib_features), ctypes.byref(lib_features_size))) - feature_list = [lib_features[i] for i in range(lib_features_size.value)] - return feature_list + check_call(_LIB.MXLibInfoFeatures(ctypes.byref(lib_features_c_array), ctypes.byref(lib_features_size))) + features = [lib_features_c_array[i] for i in range(lib_features_size.value)] + return features -def is_enabled(tocheck): +class Features(collections.OrderedDict): """ - Check for a particular feature by name + OrderedDict of name to Feature + """ + def __init__(self): + super().__init__([(f.name, f) for f in feature_list()]) - Parameters - ---------- - :param x: str The name of a valid feature as string for example 'CUDA' + def __repr__(self): + return str(list(self.values())) - Returns - ------- - :return: bool True if it's enabled, False if it's disabled, RuntimeError if the feature is not known - """ - feature_dict = {f.name: f.enabled for f in libinfo_features()} - if tocheck not in feature_dict: - raise RuntimeError("Feature '{}' is unknown, known features are: {}".format(tocheck, list(feature_dict.keys()))) - return feature_dict[tocheck] + def is_enabled(self, feature_name): + """ + Check for a particular feature by name + + Parameters + ---------- + :param x: str The name of a valid feature as string for example 'CUDA' + + Returns + ------- + :return: bool True if it's enabled, False if it's disabled, RuntimeError if the feature is not known + """ + feature_name = feature_name.upper() + if feature_name not in self: + raise RuntimeError("Feature '{}' is unknown, known features are: {}".format(feature_name, list(self.keys()))) + return self[feature_name].enabled diff --git a/tests/python/unittest/test_runtime.py b/tests/python/unittest/test_runtime.py index 59f484e61e2e..5b06d0c3c36c 100644 --- a/tests/python/unittest/test_runtime.py +++ b/tests/python/unittest/test_runtime.py @@ -21,25 +21,24 @@ from mxnet.base import MXNetError from nose.tools import * -def test_libinfo_features(): - features = libinfo_features() - print("Lib features: ") - for f in features: - print(f.name, f.enabled, f.index) - ok_(type(features) is list) - ok_(len(features) > 0) +def test_features(): + features = Features() + print(features) + ok_('CUDA' in features) + ok_(len(features) >= 30) def test_is_enabled(): - features = libinfo_features() + features = Features() for f in features: - if f.enabled: - ok_(is_enabled(f.name)) + if features[f].enabled: + ok_(features.is_enabled(f)) else: - ok_(not is_enabled(f.name)) + ok_(not features.is_enabled(f)) @raises(RuntimeError) def test_is_enabled_not_existing(): - is_enabled('this girl is on fire') + features = Features() + features.is_enabled('this girl is on fire') if __name__ == "__main__": From 834906aeee4db0be2761c14427670fa4a66bd0a6 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 14 Feb 2019 01:25:58 +0100 Subject: [PATCH 08/12] remove index as per CR suggestion --- include/mxnet/c_api.h | 1 - python/mxnet/runtime.py | 1 - src/libinfo.cc | 1 - 3 files changed, 3 deletions(-) diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h index e5e57c10faaa..13ee903407b3 100644 --- a/include/mxnet/c_api.h +++ b/include/mxnet/c_api.h @@ -141,7 +141,6 @@ struct MXCallbackList { struct LibFeature { const char* name; - uint32_t index; bool enabled; }; diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index 1fb0defba056..e6301bd88a7a 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -31,7 +31,6 @@ class Feature(ctypes.Structure): """ _fields_ = [ ("_name", ctypes.c_char_p), - ("index", ctypes.c_uint32), ("enabled", ctypes.c_bool) ] diff --git a/src/libinfo.cc b/src/libinfo.cc index 44a834c85b16..2af61eac9eca 100644 --- a/src/libinfo.cc +++ b/src/libinfo.cc @@ -114,7 +114,6 @@ LibInfo::LibInfo() { for (size_t i = 0; i < MAX_FEATURES; ++i) { m_lib_features[i].name = EnumNames::names[i].c_str(); m_lib_features[i].enabled = is_enabled(i); - m_lib_features[i].index = i; } } From e7613f6bc2d58a2babc9e7266618d979c6f0727c Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 14 Feb 2019 01:43:16 +0100 Subject: [PATCH 09/12] Fix lint --- python/mxnet/runtime.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index e6301bd88a7a..68a157611081 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -63,7 +63,7 @@ class Features(collections.OrderedDict): OrderedDict of name to Feature """ def __init__(self): - super().__init__([(f.name, f) for f in feature_list()]) + super(Features, self).__init__([(f.name, f) for f in feature_list()]) def __repr__(self): return str(list(self.values())) @@ -82,5 +82,6 @@ def is_enabled(self, feature_name): """ feature_name = feature_name.upper() if feature_name not in self: - raise RuntimeError("Feature '{}' is unknown, known features are: {}".format(feature_name, list(self.keys()))) + raise RuntimeError("Feature '{}' is unknown, known features are: {}".format( + feature_name, list(self.keys()))) return self[feature_name].enabled From 8a46442f075229ea9edae6a38f07da57746f5e31 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 14 Feb 2019 01:51:32 +0100 Subject: [PATCH 10/12] runtime --- python/mxnet/runtime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index 68a157611081..7ef5e1943072 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -22,8 +22,8 @@ """runtime querying of compile time features in the native library""" import ctypes -from .base import _LIB, check_call import collections +from .base import _LIB, check_call class Feature(ctypes.Structure): """ From cce62f100c5a2f206926e9df2dd27e8f9afc3dc2 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 14 Feb 2019 13:53:37 +0100 Subject: [PATCH 11/12] Fix doc --- docs/api/python/libinfo/libinfo.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/api/python/libinfo/libinfo.md b/docs/api/python/libinfo/libinfo.md index 7b13d77ebedf..172100590401 100644 --- a/docs/api/python/libinfo/libinfo.md +++ b/docs/api/python/libinfo/libinfo.md @@ -35,8 +35,9 @@ In [6]: .. autosummary:: :nosignatures: - LibFeature - libinfo_features + Features + Feature + feature_list ``` ## API Reference From dd432b7f241c9da2c96bcb877c2dc84e6a1f74d4 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 14 Feb 2019 15:03:04 +0000 Subject: [PATCH 12/12] Add license --- docs/api/python/libinfo/libinfo.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/api/python/libinfo/libinfo.md b/docs/api/python/libinfo/libinfo.md index 172100590401..531e1ced3c99 100644 --- a/docs/api/python/libinfo/libinfo.md +++ b/docs/api/python/libinfo/libinfo.md @@ -1,3 +1,20 @@ + + + + + + + + + + + + + + + + + # Run-Time Feature detection / Library info ```eval_rst