From ff109f520534a544a244e8f67c32fb1d4b0f33b6 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 5 Dec 2018 18:48:24 +0100 Subject: [PATCH 01/33] Prototype for runtime feature detection --- CMakeLists.txt | 2 + include/mxnet/base.h | 32 +------- include/mxnet/mxfeatures.h | 146 +++++++++++++++++++++++++++++++++++++ src/mxfeatures.cc | 91 +++++++++++++++++++++++ 4 files changed, 241 insertions(+), 30 deletions(-) create mode 100644 include/mxnet/mxfeatures.h create mode 100644 src/mxfeatures.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 23609e5ec243..18092fb4778d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -409,12 +409,14 @@ if(USE_OPENMP) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + add_definitions(-DMXNET_USE_OPENMP=1) else() if(OPENMP_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + add_definitions(-DMXNET_USE_OPENMP=1) endif() endif() elseif(UNIX AND NOT ANDROID) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index 92d9c2699d63..7fbd078bda59 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -25,6 +25,7 @@ #ifndef MXNET_BASE_H_ #define MXNET_BASE_H_ +#include "mxfeatures.h" #include #include #include @@ -36,36 +37,6 @@ #include #include -/*! - *\brief whether to use opencv support - */ -#ifndef MXNET_USE_OPENCV -#define MXNET_USE_OPENCV 1 -#endif - -/*! - *\brief whether to use cuda support - */ -#ifndef MXNET_USE_CUDA -#define MXNET_USE_CUDA MSHADOW_USE_CUDA -#endif - -/*! - *\brief whether to use cudnn library for convolution - */ -#ifndef MXNET_USE_CUDNN -#define MXNET_USE_CUDNN MSHADOW_USE_CUDNN -#endif - -/*! - *\brief whether to use cusolver library - */ -#ifndef MXNET_USE_CUSOLVER -#define MXNET_USE_CUSOLVER MSHADOW_USE_CUSOLVER -#endif - -/*! \brief Error message for using gpu when MXNET_USE_CUDA==0 */ -#define MXNET_GPU_NOT_ENABLED_ERROR "GPU is not enabled" /*! * \brief define compatible keywords in g++ @@ -412,6 +383,7 @@ inline std::ostream& operator<<(std::ostream &out, const Context &ctx) { #define MXNET_DESCRIBE(...) describe(__VA_ARGS__ "\n\nFrom:" __FILE__ ":" STRINGIZE(__LINE__)) #define ADD_FILELINE "\n\nDefined in " __FILE__ ":L" STRINGIZE(__LINE__) + #if MXNET_USE_MKLDNN == 1 constexpr size_t kMKLDNNAlign = 64; #endif diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h new file mode 100644 index 000000000000..7ae1ca46c3c4 --- /dev/null +++ b/include/mxnet/mxfeatures.h @@ -0,0 +1,146 @@ +/* + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * Copyright (c) 2018 by Contributors + * \file mxfeatures.h + * \brief check MXNet features including compile time support + */ + +#pragma once + +#include +#include + +/*! + *\brief whether to use opencv support + */ +#ifndef MXNET_USE_OPENCV +#define MXNET_USE_OPENCV 1 +#endif + +/*! + *\brief whether to use cuda support + */ +#ifndef MXNET_USE_CUDA +#define MXNET_USE_CUDA MSHADOW_USE_CUDA +#endif + +/*! + *\brief whether to use cudnn library for convolution + */ +#ifndef MXNET_USE_CUDNN +#define MXNET_USE_CUDNN MSHADOW_USE_CUDNN +#endif + +/*! + *\brief whether to use cusolver library + */ +#ifndef MXNET_USE_CUSOLVER +#define MXNET_USE_CUSOLVER MSHADOW_USE_CUSOLVER +#endif + +#ifndef MXNET_ENABLE_CUDA_RTC +#define MXNET_ENABLE_CUDA_RTC 0 +#endif + +/*! \brief Error message for using gpu when MXNET_USE_CUDA==0 */ +#define MXNET_GPU_NOT_ENABLED_ERROR "GPU is not enabled" + + +#ifndef MXNET_USE_TENSORRT +#define MXNET_USE_TENSORRT 0 +#endif + +#ifndef MXNET_USE_MKLDNN +#define MXNET_USE_MKLDNN 0 +#endif + +#ifndef MXNET_USE_OPENMP +#define MXNET_USE_OPENMP 0 +#endif + +#ifndef MXNET_USE_F16C +#define MXNET_USE_F16C MSHADOW_USE_F16C +#endif + +#ifndef MXNET_USE_CAFFE +#define MXNET_USE_CAFFE 0 +#endif + +#ifndef MXNET_USE_DIST_KVSTORE +#define MXNET_USE_DIST_KVSTORE 0 +#endif + +#ifndef MXNET_USE_SIGNAL_HANDLER +#define MXNET_USE_SIGNAL_HANDLER 0 +#endif + +#ifndef MXNET_USE_NCCL +#define MXNET_USE_NCCL 0 +#endif + + + +namespace mxnet { +namespace features { +// Check compile flags such as CMakeLists.txt + +/// Compile time features +enum : uint32_t { + // NVIDIA, CUDA + CUDA=0, + CUDNN, + NCCL, + CUDA_RTC, + TENSORRT, + + // Multiprocessing / CPU / System + OPENMP, + SSE, + F16C, + JEMALLOC, + + // Math libraries + LAPACK, + MKLDNN, + + // Image processing + OPENCV, + + // Misc + CAFFE, + PROFILER, + DIST_KVSTORE, + CXX14, + SIGNAL_HANDLER, + DEBUG, + + // size indicator + MAX_FEATURES +}; + + +/*! + * \return true if the given feature is supported + */ +bool is_enabled(uint32_t feat); + +} // namespace features +} // namespace mxnet diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc new file mode 100644 index 000000000000..d4ec84369e09 --- /dev/null +++ b/src/mxfeatures.cc @@ -0,0 +1,91 @@ +/* + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * Copyright (c) 2018 by Contributors + * \file mxfeatures.cc + * \brief check MXNet features including compile time support + */ + +#include "mxnet/mxfeatures.h" +#include "dmlc/logging.h" +#include + + +namespace mxnet { +namespace features { + +class Storage { +public: + Storage(): + feature_bits() + { + if (MXNET_USE_CUDA) + feature_bits.set(CUDA); + if (MXNET_USE_CUDNN) + feature_bits.set(CUDNN); + if (MXNET_USE_NCCL) + feature_bits.set(NCCL); + if (MXNET_USE_OPENCV) + feature_bits.set(OPENCV); + if (MXNET_ENABLE_CUDA_RTC) + feature_bits.set(CUDA_RTC); + if (MXNET_USE_TENSORRT) + feature_bits.set(TENSORRT); + if (MXNET_USE_OPENMP) + feature_bits.set(OPENMP); + if (MXNET_USE_F16C) + feature_bits.set(F16C); + if (MXNET_USE_LAPACK) + feature_bits.set(LAPACK); + if (MXNET_USE_MKLDNN) + feature_bits.set(MKLDNN); + if (MXNET_USE_OPENCV) + feature_bits.set(OPENCV); + if (MXNET_USE_CAFFE) + feature_bits.set(CAFFE); + if (MXNET_USE_DIST_KVSTORE) + feature_bits.set(DIST_KVSTORE); + if (MXNET_USE_SIGNAL_HANDLER) + feature_bits.set(SIGNAL_HANDLER); +#ifndef NDEBUG + feature_bits.set(DEBUG); +#endif + + +#if USE_JEMALLOC == 1 + feature_bits.set(JEMALLOC); +#endif + } + bool is_enabled(unsigned feat) { + CHECK_LT(feat, MAX_FEATURES); + return feature_bits.test(feat); + } +private: + std::bitset feature_bits; +}; + +static Storage storage; + +bool is_enabled(unsigned feat) { + return storage.is_enabled(feat); +} + +} // namespace features +} // namespace mxnet From 5ebc7a248879434fecec45f73af304e0462bd999 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 5 Dec 2018 19:35:57 +0100 Subject: [PATCH 02/33] Includes from diamond to quotes --- include/mxnet/base.h | 18 +++++++++--------- include/mxnet/io.h | 4 ++-- src/c_api/c_api.cc | 28 ++++++++++++++-------------- src/c_api/c_api_symbolic.cc | 12 ++++++------ 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index 7fbd078bda59..ca837145e83d 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -25,17 +25,17 @@ #ifndef MXNET_BASE_H_ #define MXNET_BASE_H_ -#include "mxfeatures.h" -#include -#include -#include -#include -#include +#include "dmlc/base.h" +#include "dmlc/io.h" +#include "dmlc/type_traits.h" +#include "dmlc/parameter.h" +#include "mshadow/tensor.h" // nnvm headers for symbolic construction. -#include -#include -#include +#include "nnvm/op.h" +#include "nnvm/tuple.h" +#include "nnvm/symbolic.h" #include +#include "mxfeatures.h" /*! diff --git a/include/mxnet/io.h b/include/mxnet/io.h index 3c806d85d56a..e61568bba0e7 100644 --- a/include/mxnet/io.h +++ b/include/mxnet/io.h @@ -25,8 +25,8 @@ #ifndef MXNET_IO_H_ #define MXNET_IO_H_ -#include -#include +#include "dmlc/data.h" +#include "dmlc/registry.h" #include #include #include diff --git a/src/c_api/c_api.cc b/src/c_api/c_api.cc index 80bd60538ff5..a9a36ca53c6c 100644 --- a/src/c_api/c_api.cc +++ b/src/c_api/c_api.cc @@ -22,20 +22,20 @@ * \file c_api.cc * \brief C API of mxnet */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "dmlc/base.h" +#include "dmlc/logging.h" +#include "dmlc/io.h" +#include "dmlc/memory_io.h" +#include "dmlc/recordio.h" +#include "dmlc/omp.h" +#include "mxnet/base.h" +#include "mxnet/ndarray.h" +#include "mxnet/operator.h" +#include "mxnet/io.h" +#include "mxnet/c_api.h" +#include "mxnet/kvstore.h" +#include "mxnet/rtc.h" +#include "mxnet/storage.h" #include #include #include diff --git a/src/c_api/c_api_symbolic.cc b/src/c_api/c_api_symbolic.cc index 73a8a7ca6f86..8517c9c8f99b 100644 --- a/src/c_api/c_api_symbolic.cc +++ b/src/c_api/c_api_symbolic.cc @@ -22,12 +22,12 @@ * \file c_api_symbolic.cc * \brief C API of mxnet */ -#include -#include -#include -#include -#include -#include +#include "mxnet/base.h" +#include "mxnet/c_api.h" +#include "nnvm/c_api.h" +#include "nnvm/pass.h" +#include "nnvm/pass_functions.h" +#include "nnvm/symbolic.h" #include "./c_api_common.h" #include "../operator/operator_common.h" #include "../executor/exec_pass.h" From 30f057f18420c0563c7fb6660345d1640fe19674 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 8 Jan 2019 15:56:03 +0100 Subject: [PATCH 03/33] Add CPU feature and BLAS flavour flags --- include/mxnet/mxfeatures.h | 22 +++++++++++++++++++++- src/mxfeatures.cc | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h index 7ae1ca46c3c4..75cdf4106346 100644 --- a/include/mxnet/mxfeatures.h +++ b/include/mxnet/mxfeatures.h @@ -111,14 +111,33 @@ enum : uint32_t { CUDA_RTC, TENSORRT, + // CPU Features / optimizations + CPU_SSE, + CPU_SSE2, + CPU_SSE3, + CPU_SSE4_1, + CPU_SSE4_2, + CPU_SSE4A, // AMD extensions to SSE4 + CPU_AVX, + CPU_AVX2, + + // Multiprocessing / CPU / System OPENMP, SSE, F16C, JEMALLOC, - // Math libraries + // Math libraries & BLAS + // Flavour of BLAS + BLAS_OPEN, + BLAS_ATLAS, + // Intel(R) Math Kernel Library + BLAS_MKL, + // Other math libraries: + // Linear Algebra PACKage LAPACK, + // Intel(R) Math Kernel Library for Deep Neural Networks MKLDNN, // Image processing @@ -129,6 +148,7 @@ enum : uint32_t { PROFILER, DIST_KVSTORE, CXX14, + // Signal handler to print stack traces on exceptions SIGNAL_HANDLER, DEBUG, diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc index d4ec84369e09..4d471044621d 100644 --- a/src/mxfeatures.cc +++ b/src/mxfeatures.cc @@ -31,6 +31,7 @@ namespace mxnet { namespace features { + class Storage { public: Storage(): From e9eff40d9fcf19c991547cb86aaff3d8abb4c313 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 8 Jan 2019 16:39:46 +0100 Subject: [PATCH 04/33] Add BLAS flavour and CPU SSE and AVX flags --- Makefile | 10 +++++ cmake/ChooseBlas.cmake | 4 ++ include/mxnet/mxfeatures.h | 26 ++++++++++-- src/mxfeatures.cc | 87 ++++++++++++++++++++++++-------------- 4 files changed, 92 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 42010e42b08c..f4769c36fe6a 100644 --- a/Makefile +++ b/Makefile @@ -212,6 +212,16 @@ ifeq ($(USE_CUDNN), 1) LDFLAGS += -lcudnn endif +ifeq ($(use_blas), open) + CFLAGS += -DMXNET_USE_BLAS_OPEN=1 +else ifeq ($(use_blas), atlas) + CFLAGS += -DMXNET_USE_BLAS_ATLAS=1 +else ifeq ($(use_blas), mkl) + CFLAGS += -DMXNET_USE_BLAS_MKL=1 +else ifeq ($(use_blas), apple) + CFLAGS += -DMXNET_USE_BLAS_APPLE=1 +endif + # whether to use F16C instruction set extension for fast fp16 compute on CPU # if cross compiling you may want to explicitly turn it off if target system does not support it ifndef USE_F16C diff --git a/cmake/ChooseBlas.cmake b/cmake/ChooseBlas.cmake index 13d7083f3d12..5f4af2d89c91 100644 --- a/cmake/ChooseBlas.cmake +++ b/cmake/ChooseBlas.cmake @@ -37,22 +37,26 @@ if(BLAS STREQUAL "Atlas" OR BLAS STREQUAL "atlas") list(APPEND mshadow_LINKER_LIBS ${Atlas_LIBRARIES}) add_definitions(-DMSHADOW_USE_CBLAS=1) add_definitions(-DMSHADOW_USE_MKL=0) + add_definitions(-DMXNET_USE_BLAS_ATLAS=1) elseif(BLAS STREQUAL "Open" OR BLAS STREQUAL "open") find_package(OpenBLAS REQUIRED) include_directories(SYSTEM ${OpenBLAS_INCLUDE_DIR}) list(APPEND mshadow_LINKER_LIBS ${OpenBLAS_LIB}) add_definitions(-DMSHADOW_USE_CBLAS=1) add_definitions(-DMSHADOW_USE_MKL=0) + add_definitions(-DMXNET_USE_BLAS_OPEN=1) elseif(BLAS STREQUAL "MKL" OR BLAS STREQUAL "mkl") find_package(MKL REQUIRED) include_directories(SYSTEM ${MKL_INCLUDE_DIR}) list(APPEND mshadow_LINKER_LIBS ${MKL_LIBRARIES}) add_definitions(-DMSHADOW_USE_CBLAS=0) add_definitions(-DMSHADOW_USE_MKL=1) + add_definitions(-DMXNET_USE_BLAS_MKL=1) elseif(BLAS STREQUAL "apple") find_package(Accelerate REQUIRED) include_directories(SYSTEM ${Accelerate_INCLUDE_DIR}) list(APPEND mshadow_LINKER_LIBS ${Accelerate_LIBRARIES}) add_definitions(-DMSHADOW_USE_MKL=0) add_definitions(-DMSHADOW_USE_CBLAS=1) + add_definitions(-DMXNET_USE_BLAS_APPLE=1) endif() diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h index 75cdf4106346..ebc996f9dd24 100644 --- a/include/mxnet/mxfeatures.h +++ b/include/mxnet/mxfeatures.h @@ -49,6 +49,10 @@ #define MXNET_USE_CUDNN MSHADOW_USE_CUDNN #endif +#ifndef MXNET_USE_NCCL +#define MXNET_USE_NCCL 0 +#endif + /*! *\brief whether to use cusolver library */ @@ -68,6 +72,23 @@ #define MXNET_USE_TENSORRT 0 #endif + +#ifndef MXNET_USE_BLAS_ATLAS +#define MXNET_USE_BLAS_ATLAS 0 +#endif + +#ifndef MXNET_USE_BLAS_OPEN +#define MXNET_USE_BLAS_OPEN 0 +#endif + +#ifndef MXNET_USE_BLAS_MKL +#define MXNET_USE_BLAS_MKL 0 +#endif + +#ifndef MXNET_USE_BLAS_APPLE +#define MXNET_USE_BLAS_APPLE 0 +#endif + #ifndef MXNET_USE_MKLDNN #define MXNET_USE_MKLDNN 0 #endif @@ -92,9 +113,7 @@ #define MXNET_USE_SIGNAL_HANDLER 0 #endif -#ifndef MXNET_USE_NCCL -#define MXNET_USE_NCCL 0 -#endif + @@ -134,6 +153,7 @@ enum : uint32_t { BLAS_ATLAS, // Intel(R) Math Kernel Library BLAS_MKL, + BLAS_APPLE, // Other math libraries: // Linear Algebra PACKage LAPACK, diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc index 4d471044621d..d365ef183a90 100644 --- a/src/mxfeatures.cc +++ b/src/mxfeatures.cc @@ -1,4 +1,4 @@ -/* + /* * 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 @@ -37,44 +37,67 @@ class Storage { Storage(): feature_bits() { - if (MXNET_USE_CUDA) - feature_bits.set(CUDA); - if (MXNET_USE_CUDNN) - feature_bits.set(CUDNN); - if (MXNET_USE_NCCL) - feature_bits.set(NCCL); - if (MXNET_USE_OPENCV) - feature_bits.set(OPENCV); - if (MXNET_ENABLE_CUDA_RTC) - feature_bits.set(CUDA_RTC); - if (MXNET_USE_TENSORRT) - feature_bits.set(TENSORRT); - if (MXNET_USE_OPENMP) - feature_bits.set(OPENMP); - if (MXNET_USE_F16C) - feature_bits.set(F16C); - if (MXNET_USE_LAPACK) - feature_bits.set(LAPACK); - if (MXNET_USE_MKLDNN) - feature_bits.set(MKLDNN); - if (MXNET_USE_OPENCV) - feature_bits.set(OPENCV); - if (MXNET_USE_CAFFE) - feature_bits.set(CAFFE); - if (MXNET_USE_DIST_KVSTORE) - feature_bits.set(DIST_KVSTORE); - if (MXNET_USE_SIGNAL_HANDLER) - feature_bits.set(SIGNAL_HANDLER); + // GPU + feature_bits.set(CUDA, MXNET_USE_CUDA); + feature_bits.set(CUDNN, MXNET_USE_CUDNN); + feature_bits.set(NCCL, MXNET_USE_NCCL); + feature_bits.set(CUDA_RTC, MXNET_ENABLE_CUDA_RTC); + feature_bits.set(TENSORRT, MXNET_USE_TENSORRT); + + // Check flags for example with gcc -msse3 -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" +#if __SSE__ + feature_bits.set(CPU_SSE); +#endif +#if __SSE2__ + feature_bits.set(CPU_SSE2); +#endif +#if __SSE3__ + feature_bits.set(CPU_SSE3); +#endif +#if __SSE4_1__ + feature_bits.set(CPU_SSE4_1); +#endif +#if __SSE4_2__ + feature_bits.set(CPU_SSE4_2); +#endif +#if __SSE4A__ + feature_bits.set(CPU_SSE4A); +#endif +#if __AVX__ + feature_bits.set(CPU_AVX); +#endif +#if __AVX2__ + feature_bits.set(CPU_AVX2); +#endif + + // CPU + feature_bits.set(OPENMP, MXNET_USE_OPENMP); + feature_bits.set(F16C, MXNET_USE_F16C); + + // Math + feature_bits.set(BLAS_OPEN, MXNET_USE_BLAS_OPEN); + feature_bits.set(BLAS_ATLAS, MXNET_USE_BLAS_ATLAS); + feature_bits.set(BLAS_MKL, MXNET_USE_BLAS_MKL); + feature_bits.set(BLAS_APPLE, MXNET_USE_BLAS_APPLE); + feature_bits.set(LAPACK, MXNET_USE_LAPACK); + feature_bits.set(MKLDNN, MXNET_USE_MKLDNN); + + // Image + feature_bits.set(OPENCV, MXNET_USE_OPENCV); + + // Misc + feature_bits.set(CAFFE, MXNET_USE_CAFFE); + feature_bits.set(DIST_KVSTORE, MXNET_USE_DIST_KVSTORE); + feature_bits.set(SIGNAL_HANDLER, MXNET_USE_SIGNAL_HANDLER); #ifndef NDEBUG feature_bits.set(DEBUG); #endif - #if USE_JEMALLOC == 1 feature_bits.set(JEMALLOC); #endif } - bool is_enabled(unsigned feat) { + bool is_enabled(const unsigned feat) const { CHECK_LT(feat, MAX_FEATURES); return feature_bits.test(feat); } @@ -84,7 +107,7 @@ class Storage { static Storage storage; -bool is_enabled(unsigned feat) { +bool is_enabled(const unsigned feat) { return storage.is_enabled(feat); } From 2e60d236156295e19eeeb0455b7e0469c2d64b9e Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 8 Jan 2019 22:12:56 +0100 Subject: [PATCH 05/33] MXNET_USE_LAPACK --- include/mxnet/mxfeatures.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h index ebc996f9dd24..b43f77d54d7d 100644 --- a/include/mxnet/mxfeatures.h +++ b/include/mxnet/mxfeatures.h @@ -89,6 +89,10 @@ #define MXNET_USE_BLAS_APPLE 0 #endif +#ifndef MXNET_USE_LAPACK +#define MXNET_USE_LAPACK 0 +#endif + #ifndef MXNET_USE_MKLDNN #define MXNET_USE_MKLDNN 0 #endif From d9130332602053fe377890c51512c7f82bc2e0cd Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 8 Jan 2019 23:50:19 +0100 Subject: [PATCH 06/33] Fix C++ linting errors --- include/mxnet/base.h | 2 +- include/mxnet/io.h | 4 ++-- include/mxnet/mxfeatures.h | 6 +++--- src/mxfeatures.cc | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index ca837145e83d..f88b22784a1b 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -26,6 +26,7 @@ #define MXNET_BASE_H_ #include "dmlc/base.h" +#include #include "dmlc/io.h" #include "dmlc/type_traits.h" #include "dmlc/parameter.h" @@ -34,7 +35,6 @@ #include "nnvm/op.h" #include "nnvm/tuple.h" #include "nnvm/symbolic.h" -#include #include "mxfeatures.h" diff --git a/include/mxnet/io.h b/include/mxnet/io.h index e61568bba0e7..e18f03ed0ef3 100644 --- a/include/mxnet/io.h +++ b/include/mxnet/io.h @@ -25,12 +25,12 @@ #ifndef MXNET_IO_H_ #define MXNET_IO_H_ -#include "dmlc/data.h" -#include "dmlc/registry.h" #include #include #include #include +#include "dmlc/data.h" +#include "dmlc/registry.h" #include "./base.h" #include "./ndarray.h" diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h index b43f77d54d7d..c40fc1933f27 100644 --- a/include/mxnet/mxfeatures.h +++ b/include/mxnet/mxfeatures.h @@ -25,8 +25,8 @@ #pragma once -#include -#include +#include "dmlc/base.h" +#include "mshadow/base.h" /*! *\brief whether to use opencv support @@ -128,7 +128,7 @@ namespace features { /// Compile time features enum : uint32_t { // NVIDIA, CUDA - CUDA=0, + CUDA = 0, CUDNN, NCCL, CUDA_RTC, diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc index d365ef183a90..705de1e50142 100644 --- a/src/mxfeatures.cc +++ b/src/mxfeatures.cc @@ -24,8 +24,8 @@ */ #include "mxnet/mxfeatures.h" -#include "dmlc/logging.h" #include +#include "dmlc/logging.h" namespace mxnet { @@ -33,10 +33,9 @@ namespace features { class Storage { -public: + public: Storage(): - feature_bits() - { + feature_bits() { // GPU feature_bits.set(CUDA, MXNET_USE_CUDA); feature_bits.set(CUDNN, MXNET_USE_CUDNN); @@ -101,7 +100,8 @@ class Storage { CHECK_LT(feat, MAX_FEATURES); return feature_bits.test(feat); } -private: + + private: std::bitset feature_bits; }; From 939d76c8f18960d1e832cb45b6e651d0834d786a Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 9 Jan 2019 01:38:49 +0100 Subject: [PATCH 07/33] Expose runtime feature detection in the public C API and in the Python API --- include/mxnet/c_api.h | 10 +++ python/mxnet/mxfeatures.py | 91 ++++++++++++++++++++++++++ src/c_api/c_api.cc | 22 +++++-- tests/python/unittest/test_features.py | 34 ++++++++++ 4 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 python/mxnet/mxfeatures.py create mode 100644 tests/python/unittest/test_features.py diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h index e9f1e2d6cccc..79f2bf518696 100644 --- a/include/mxnet/c_api.h +++ b/include/mxnet/c_api.h @@ -208,6 +208,15 @@ MXNET_DLL const char *MXGetLastError(); //------------------------------------- // Part 0: Global State setups //------------------------------------- + +/*! + * \brief + * \param feature to check mxfeatures.h + * \param out set to true if the feature is enabled, false otherwise + * \return 0 when success, -1 when failure happens. + */ +MXNET_DLL int MXHasFeature(const mx_uint feature, bool* out); + /*! * \brief Seed all global random number generators in mxnet. * \param seed the random number seed. @@ -465,6 +474,7 @@ MXNET_DLL int MXGetGPUMemoryInformation64(int dev, uint64_t *free_mem, uint64_t */ MXNET_DLL int MXGetVersion(int *out); + //------------------------------------- // Part 1: NDArray creation and deletion //------------------------------------- diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/mxfeatures.py new file mode 100644 index 000000000000..eb03ba660033 --- /dev/null +++ b/python/mxnet/mxfeatures.py @@ -0,0 +1,91 @@ + # 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 +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# coding: utf-8 +# pylint: disable=invalid-name, no-member, trailing-comma-tuple, bad-mcs-classmethod-argument + +"""runtime detection of compile time features in the native library""" + +import ctypes +import enum +from .base import _LIB, check_call, mx_uint + +feature_names = [ + "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" +] + + +Feature = enum.Enum('Feature', {name: index for index, name in enumerate(feature_names)}) + + +def has_feature(feature): + """ + Check the library for compile-time feature at runtime + + Parameters + ---------- + feature : int + An integer representing the feature to check + + Returns + ------- + boolean + True if the feature is enabled, false otherwise + """ + res = ctypes.c_bool() + check_call(_LIB.MXHasFeature(mx_uint(feature), ctypes.byref(res))) + return res.value + + +def features_enabled(): + res = [] + for f in Feature: + if has_feature(f.value): + res.append(f) + return res + +def features_enabled_str(sep=', '): + return sep.join(map(lambda x: x.name, features_enabled())) diff --git a/src/c_api/c_api.cc b/src/c_api/c_api.cc index a9a36ca53c6c..b436e8ca601b 100644 --- a/src/c_api/c_api.cc +++ b/src/c_api/c_api.cc @@ -22,6 +22,13 @@ * \file c_api.cc * \brief C API of mxnet */ +#include +#include +#include +#include +#include +#include +#include #include "dmlc/base.h" #include "dmlc/logging.h" #include "dmlc/io.h" @@ -36,13 +43,7 @@ #include "mxnet/kvstore.h" #include "mxnet/rtc.h" #include "mxnet/storage.h" -#include -#include -#include -#include -#include -#include -#include +#include "mxnet/mxfeatures.h" #include "./c_api_common.h" #include "../operator/custom/custom-inl.h" #include "../operator/tensor/matrix_op-inl.h" @@ -85,6 +86,13 @@ inline int MXAPIGetFunctionRegInfo(const FunRegType *e, } // NOTE: return value is added in API_END + +int MXHasFeature(const mx_uint feature, bool* out) { + API_BEGIN(); + *out = features::is_enabled(feature); + API_END(); +} + int MXRandomSeed(int seed) { API_BEGIN(); mxnet::RandomSeed(seed); diff --git a/tests/python/unittest/test_features.py b/tests/python/unittest/test_features.py new file mode 100644 index 000000000000..34f7f07868a3 --- /dev/null +++ b/tests/python/unittest/test_features.py @@ -0,0 +1,34 @@ +# 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 +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import mxnet as mx +from mxnet.mxfeatures import * +from nose.tools import * + +def test_runtime_features(): + for f in Feature: + res = has_feature(f.value) + ok_(type(res) is bool) + for f in features_enabled(): + ok_(type(f) is Feature) + ok_(type(features_enabled_str()) is str) + print("Features enabled: {}".format(features_enabled_str())) + + +if __name__ == "__main__": + import nose + nose.runmodule() From 80ae05e28ec38248c3cd6f8569ffc05326e347e6 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 9 Jan 2019 01:47:20 +0100 Subject: [PATCH 08/33] Refactor Storage -> FeatureSet --- src/mxfeatures.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc index 705de1e50142..0397826a8457 100644 --- a/src/mxfeatures.cc +++ b/src/mxfeatures.cc @@ -32,9 +32,9 @@ namespace mxnet { namespace features { -class Storage { +class FeatureSet { public: - Storage(): + FeatureSet(): feature_bits() { // GPU feature_bits.set(CUDA, MXNET_USE_CUDA); @@ -105,10 +105,10 @@ class Storage { std::bitset feature_bits; }; -static Storage storage; +static FeatureSet featureSet; bool is_enabled(const unsigned feat) { - return storage.is_enabled(feat); + return featureSet.is_enabled(feat); } } // namespace features From c6bdb54f0767ed559e1f22df287fcd5be6ae65ee Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 9 Jan 2019 01:58:10 +0100 Subject: [PATCH 09/33] Refine documentation --- python/mxnet/mxfeatures.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/mxfeatures.py index eb03ba660033..54c9ddfe622b 100644 --- a/python/mxnet/mxfeatures.py +++ b/python/mxnet/mxfeatures.py @@ -81,6 +81,12 @@ def has_feature(feature): def features_enabled(): + """ + Returns + ------- + features: list of Feature + list of enabled features in the back-end + """ res = [] for f in Feature: if has_feature(f.value): @@ -88,4 +94,10 @@ def features_enabled(): return res def features_enabled_str(sep=', '): + """ + Returns + ------- + string with a comma separated list of enabled features in the back-end. For example: + "CPU_SSE, OPENMP, F16C, LAPACK, MKLDNN, OPENCV, SIGNAL_HANDLER, DEBUG" + """ return sep.join(map(lambda x: x.name, features_enabled())) From a27af1052961b1572bb6e6e4c71f22993cfb9a82 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 9 Jan 2019 02:08:18 +0100 Subject: [PATCH 10/33] Add failure case --- tests/python/unittest/test_features.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/python/unittest/test_features.py b/tests/python/unittest/test_features.py index 34f7f07868a3..ff9118100e41 100644 --- a/tests/python/unittest/test_features.py +++ b/tests/python/unittest/test_features.py @@ -16,7 +16,9 @@ # under the License. import mxnet as mx +import sys from mxnet.mxfeatures import * +from mxnet.base import MXNetError from nose.tools import * def test_runtime_features(): @@ -28,6 +30,10 @@ def test_runtime_features(): ok_(type(features_enabled_str()) is str) print("Features enabled: {}".format(features_enabled_str())) +@raises(MXNetError) +def test_has_feature_2large(): + has_feature(sys.maxsize) + if __name__ == "__main__": import nose From 799a567313abaca684912291b8d07502816e58ea Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 9 Jan 2019 02:47:42 +0100 Subject: [PATCH 11/33] Fix pylint --- python/mxnet/gluon/utils.py | 2 +- python/mxnet/mxfeatures.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/mxnet/gluon/utils.py b/python/mxnet/gluon/utils.py index 78324986760a..55edd950d223 100644 --- a/python/mxnet/gluon/utils.py +++ b/python/mxnet/gluon/utils.py @@ -222,7 +222,7 @@ def _replace_atomic(src, dst): _MOVEFILE_WRITE_THROUGH = 0x8 _windows_default_flags = _MOVEFILE_WRITE_THROUGH - text_type = unicode if sys.version_info[0] == 2 else str # noqa + text_type = unicode if sys.version_info[0] == 2 else str # pylint: disable=undefined-variable def _str_to_unicode(x): """Handle text decoding. Internal use only""" diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/mxfeatures.py index 54c9ddfe622b..22c94f423c59 100644 --- a/python/mxnet/mxfeatures.py +++ b/python/mxnet/mxfeatures.py @@ -16,7 +16,7 @@ # under the License. # coding: utf-8 -# pylint: disable=invalid-name, no-member, trailing-comma-tuple, bad-mcs-classmethod-argument +# pylint: disable=not-an-iterable """runtime detection of compile time features in the native library""" From ba356cfb2dfebf602e484e54303f153ee2adaf25 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Tue, 15 Jan 2019 12:24:19 +0100 Subject: [PATCH 12/33] Address CR comments --- include/mxnet/mxfeatures.h | 104 ++++++++++++++++++------------------- python/mxnet/mxfeatures.py | 2 +- src/mxfeatures.cc | 97 +++++++++++++++++----------------- 3 files changed, 99 insertions(+), 104 deletions(-) diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h index c40fc1933f27..10f9b3656692 100644 --- a/include/mxnet/mxfeatures.h +++ b/include/mxnet/mxfeatures.h @@ -119,65 +119,63 @@ - - namespace mxnet { namespace features { // Check compile flags such as CMakeLists.txt /// Compile time features enum : uint32_t { - // NVIDIA, CUDA - CUDA = 0, - CUDNN, - NCCL, - CUDA_RTC, - TENSORRT, - - // CPU Features / optimizations - CPU_SSE, - CPU_SSE2, - CPU_SSE3, - CPU_SSE4_1, - CPU_SSE4_2, - CPU_SSE4A, // AMD extensions to SSE4 - CPU_AVX, - CPU_AVX2, - - - // Multiprocessing / CPU / System - OPENMP, - SSE, - F16C, - JEMALLOC, - - // Math libraries & BLAS - // Flavour of BLAS - BLAS_OPEN, - BLAS_ATLAS, - // Intel(R) Math Kernel Library - BLAS_MKL, - BLAS_APPLE, - // Other math libraries: - // Linear Algebra PACKage - LAPACK, - // Intel(R) Math Kernel Library for Deep Neural Networks - MKLDNN, - - // Image processing - OPENCV, - - // Misc - CAFFE, - PROFILER, - DIST_KVSTORE, - CXX14, - // Signal handler to print stack traces on exceptions - SIGNAL_HANDLER, - DEBUG, - - // size indicator - MAX_FEATURES + // NVIDIA, CUDA + CUDA = 0, + CUDNN, + NCCL, + CUDA_RTC, + TENSORRT, + + // CPU Features / optimizations + CPU_SSE, + CPU_SSE2, + CPU_SSE3, + CPU_SSE4_1, + CPU_SSE4_2, + CPU_SSE4A, // AMD extensions to SSE4 + CPU_AVX, + CPU_AVX2, + + + // Multiprocessing / CPU / System + OPENMP, + SSE, + F16C, + JEMALLOC, + + // Math libraries & BLAS + // Flavour of BLAS + BLAS_OPEN, + BLAS_ATLAS, + // Intel(R) Math Kernel Library + BLAS_MKL, + BLAS_APPLE, + // Other math libraries: + // Linear Algebra PACKage + LAPACK, + // Intel(R) Math Kernel Library for Deep Neural Networks + MKLDNN, + + // Image processing + OPENCV, + + // Misc + CAFFE, + PROFILER, + DIST_KVSTORE, + CXX14, + // Signal handler to print stack traces on exceptions + SIGNAL_HANDLER, + DEBUG, + + // size indicator + MAX_FEATURES }; diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/mxfeatures.py index 22c94f423c59..c546151ab06d 100644 --- a/python/mxnet/mxfeatures.py +++ b/python/mxnet/mxfeatures.py @@ -1,4 +1,4 @@ - # Licensed to the Apache Software Foundation (ASF) under one +# 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 # regarding copyright ownership. The ASF licenses this file diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc index 0397826a8457..7a435d7c81c9 100644 --- a/src/mxfeatures.cc +++ b/src/mxfeatures.cc @@ -1,4 +1,4 @@ - /* +/* * 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 @@ -25,90 +25,87 @@ #include "mxnet/mxfeatures.h" #include -#include "dmlc/logging.h" - namespace mxnet { namespace features { - class FeatureSet { public: - FeatureSet(): - feature_bits() { - // GPU - feature_bits.set(CUDA, MXNET_USE_CUDA); - feature_bits.set(CUDNN, MXNET_USE_CUDNN); - feature_bits.set(NCCL, MXNET_USE_NCCL); - feature_bits.set(CUDA_RTC, MXNET_ENABLE_CUDA_RTC); - feature_bits.set(TENSORRT, MXNET_USE_TENSORRT); - - // Check flags for example with gcc -msse3 -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" + FeatureSet() : + feature_bits() { + // GPU + feature_bits.set(CUDA, MXNET_USE_CUDA); + feature_bits.set(CUDNN, MXNET_USE_CUDNN); + feature_bits.set(NCCL, MXNET_USE_NCCL); + feature_bits.set(CUDA_RTC, MXNET_ENABLE_CUDA_RTC); + feature_bits.set(TENSORRT, MXNET_USE_TENSORRT); + + // Check flags for example with gcc -msse3 -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" #if __SSE__ - feature_bits.set(CPU_SSE); + feature_bits.set(CPU_SSE); #endif #if __SSE2__ - feature_bits.set(CPU_SSE2); + feature_bits.set(CPU_SSE2); #endif #if __SSE3__ - feature_bits.set(CPU_SSE3); + feature_bits.set(CPU_SSE3); #endif #if __SSE4_1__ - feature_bits.set(CPU_SSE4_1); + feature_bits.set(CPU_SSE4_1); #endif #if __SSE4_2__ - feature_bits.set(CPU_SSE4_2); + feature_bits.set(CPU_SSE4_2); #endif #if __SSE4A__ - feature_bits.set(CPU_SSE4A); + feature_bits.set(CPU_SSE4A); #endif #if __AVX__ - feature_bits.set(CPU_AVX); + feature_bits.set(CPU_AVX); #endif #if __AVX2__ - feature_bits.set(CPU_AVX2); + feature_bits.set(CPU_AVX2); #endif - // CPU - feature_bits.set(OPENMP, MXNET_USE_OPENMP); - feature_bits.set(F16C, MXNET_USE_F16C); - - // Math - feature_bits.set(BLAS_OPEN, MXNET_USE_BLAS_OPEN); - feature_bits.set(BLAS_ATLAS, MXNET_USE_BLAS_ATLAS); - feature_bits.set(BLAS_MKL, MXNET_USE_BLAS_MKL); - feature_bits.set(BLAS_APPLE, MXNET_USE_BLAS_APPLE); - feature_bits.set(LAPACK, MXNET_USE_LAPACK); - feature_bits.set(MKLDNN, MXNET_USE_MKLDNN); - - // Image - feature_bits.set(OPENCV, MXNET_USE_OPENCV); - - // Misc - feature_bits.set(CAFFE, MXNET_USE_CAFFE); - feature_bits.set(DIST_KVSTORE, MXNET_USE_DIST_KVSTORE); - feature_bits.set(SIGNAL_HANDLER, MXNET_USE_SIGNAL_HANDLER); + // CPU + feature_bits.set(OPENMP, MXNET_USE_OPENMP); + feature_bits.set(F16C, MXNET_USE_F16C); + + // Math + feature_bits.set(BLAS_OPEN, MXNET_USE_BLAS_OPEN); + feature_bits.set(BLAS_ATLAS, MXNET_USE_BLAS_ATLAS); + feature_bits.set(BLAS_MKL, MXNET_USE_BLAS_MKL); + feature_bits.set(BLAS_APPLE, MXNET_USE_BLAS_APPLE); + feature_bits.set(LAPACK, MXNET_USE_LAPACK); + feature_bits.set(MKLDNN, MXNET_USE_MKLDNN); + + // Image + feature_bits.set(OPENCV, MXNET_USE_OPENCV); + + // Misc + feature_bits.set(CAFFE, MXNET_USE_CAFFE); + feature_bits.set(DIST_KVSTORE, MXNET_USE_DIST_KVSTORE); + feature_bits.set(SIGNAL_HANDLER, MXNET_USE_SIGNAL_HANDLER); #ifndef NDEBUG - feature_bits.set(DEBUG); + feature_bits.set(DEBUG); #endif #if USE_JEMALLOC == 1 - feature_bits.set(JEMALLOC); + feature_bits.set(JEMALLOC); #endif - } - bool is_enabled(const unsigned feat) const { - CHECK_LT(feat, MAX_FEATURES); - return feature_bits.test(feat); - } + } + bool is_enabled(const unsigned feat) const { + CHECK_LT(feat, MAX_FEATURES); + return feature_bits.test(feat); + } private: - std::bitset feature_bits; + std::bitset feature_bits; }; static FeatureSet featureSet; bool is_enabled(const unsigned feat) { - return featureSet.is_enabled(feat); + return featureSet.is_enabled(feat); } } // namespace features From 09e68a6cdff0c3f73bbf177a9a5fa4f1f57b65a7 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 02:30:15 +0100 Subject: [PATCH 13/33] Address CR comments --- include/mxnet/base.h | 2 +- include/mxnet/c_api.h | 15 +++- include/mxnet/{mxfeatures.h => mxruntime.h} | 10 ++- python/mxnet/{mxfeatures.py => runtime.py} | 73 +++++++------------ src/c_api/c_api.cc | 20 ++++- src/{mxfeatures.cc => mxruntime.cc} | 37 +++++++++- tests/cpp/misc/runtime_test.cc | 32 ++++++++ .../{test_features.py => test_runtime.py} | 10 +-- 8 files changed, 137 insertions(+), 62 deletions(-) rename include/mxnet/{mxfeatures.h => mxruntime.h} (94%) rename python/mxnet/{mxfeatures.py => runtime.py} (61%) rename src/{mxfeatures.cc => mxruntime.cc} (85%) create mode 100644 tests/cpp/misc/runtime_test.cc rename tests/python/unittest/{test_features.py => test_runtime.py} (84%) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index f88b22784a1b..14902d585a40 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -35,7 +35,7 @@ #include "nnvm/op.h" #include "nnvm/tuple.h" #include "nnvm/symbolic.h" -#include "mxfeatures.h" +#include "mxruntime.h" /*! diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h index 79f2bf518696..768d73a33d3d 100644 --- a/include/mxnet/c_api.h +++ b/include/mxnet/c_api.h @@ -210,12 +210,21 @@ MXNET_DLL const char *MXGetLastError(); //------------------------------------- /*! - * \brief - * \param feature to check mxfeatures.h + * \brief Check if a feature is enabled in the runtime + * \param feature to check mxruntime.h * \param out set to true if the feature is enabled, false otherwise * \return 0 when success, -1 when failure happens. */ -MXNET_DLL int MXHasFeature(const mx_uint feature, bool* out); +MXNET_DLL int MXRuntimeHasFeature(const mx_uint feature, bool *out); + + +/*! + * \brief Return a list of supported runtime features not enabled inclusive. + * \param size size of the returned array + * \param names ptr to array of strings containing feature names + * \return 0 when success, -1 when failure happens. + */ +MXNET_DLL int MXRuntimeFeatureList(size_t *size, const char ***names); /*! * \brief Seed all global random number generators in mxnet. diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxruntime.h similarity index 94% rename from include/mxnet/mxfeatures.h rename to include/mxnet/mxruntime.h index 10f9b3656692..6a52b51a3d1a 100644 --- a/include/mxnet/mxfeatures.h +++ b/include/mxnet/mxruntime.h @@ -1,4 +1,4 @@ -/* + /* * 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 @@ -19,12 +19,13 @@ /*! * Copyright (c) 2018 by Contributors - * \file mxfeatures.h + * \file mxruntime.h * \brief check MXNet features including compile time support */ #pragma once +#include #include "dmlc/base.h" #include "mshadow/base.h" @@ -124,6 +125,7 @@ namespace features { // Check compile flags such as CMakeLists.txt /// Compile time features +// ATTENTION: When changing this enum, match the strings in mxruntime.cc!!! enum : uint32_t { // NVIDIA, CUDA CUDA = 0, @@ -179,6 +181,10 @@ enum : uint32_t { }; +struct EnumNames { + static const std::vector names; +}; + /*! * \return true if the given feature is supported */ diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/runtime.py similarity index 61% rename from python/mxnet/mxfeatures.py rename to python/mxnet/runtime.py index c546151ab06d..f140fe4d47d7 100644 --- a/python/mxnet/mxfeatures.py +++ b/python/mxnet/runtime.py @@ -22,46 +22,34 @@ import ctypes import enum -from .base import _LIB, check_call, mx_uint +from .base import _LIB, check_call, mx_uint, py_str -feature_names = [ - "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" -] +def _feature_names_available(): + """ + + :return: + """ + feature_list = ctypes.POINTER(ctypes.c_char_p)() + feature_list_sz = ctypes.c_size_t() + check_call(_LIB.MXRuntimeFeatureList(ctypes.byref(feature_list_sz), ctypes.byref(feature_list))) + feature_names = [] + for i in range(feature_list_sz.value): + feature_names.append(py_str(feature_list[i])) + return feature_names -Feature = enum.Enum('Feature', {name: index for index, name in enumerate(feature_names)}) +Feature = enum.Enum('Feature', {name: index for index, name in enumerate(_feature_names_available())}) +def features_available(): + """ + Returns + ------- + features: list of Feature enum + Features available in the backend which includes disabled and enabled ones + """ + return list(Feature) -def has_feature(feature): +def has_feature_index(feature): """ Check the library for compile-time feature at runtime @@ -76,7 +64,7 @@ def has_feature(feature): True if the feature is enabled, false otherwise """ res = ctypes.c_bool() - check_call(_LIB.MXHasFeature(mx_uint(feature), ctypes.byref(res))) + check_call(_LIB.MXRuntimeHasFeature(mx_uint(feature), ctypes.byref(res))) return res.value @@ -84,20 +72,11 @@ def features_enabled(): """ Returns ------- - features: list of Feature + features: list of Feature enum list of enabled features in the back-end """ res = [] for f in Feature: - if has_feature(f.value): + if has_feature_index(f.value): res.append(f) return res - -def features_enabled_str(sep=', '): - """ - Returns - ------- - string with a comma separated list of enabled features in the back-end. For example: - "CPU_SSE, OPENMP, F16C, LAPACK, MKLDNN, OPENCV, SIGNAL_HANDLER, DEBUG" - """ - return sep.join(map(lambda x: x.name, features_enabled())) diff --git a/src/c_api/c_api.cc b/src/c_api/c_api.cc index b436e8ca601b..3fec0a3a5364 100644 --- a/src/c_api/c_api.cc +++ b/src/c_api/c_api.cc @@ -43,7 +43,7 @@ #include "mxnet/kvstore.h" #include "mxnet/rtc.h" #include "mxnet/storage.h" -#include "mxnet/mxfeatures.h" +#include "mxnet/mxruntime.h" #include "./c_api_common.h" #include "../operator/custom/custom-inl.h" #include "../operator/tensor/matrix_op-inl.h" @@ -87,12 +87,28 @@ inline int MXAPIGetFunctionRegInfo(const FunRegType *e, // NOTE: return value is added in API_END -int MXHasFeature(const mx_uint feature, bool* out) { +int MXRuntimeHasFeature(const mx_uint feature, bool *out) { API_BEGIN(); *out = features::is_enabled(feature); API_END(); } +int MXRuntimeFeatureList(size_t *size, const char ***names) { + API_BEGIN(); + MXAPIThreadLocalEntry *ret = MXAPIThreadLocalStore::Get(); + ret->ret_vec_str.resize(0); + ret->ret_vec_charp.resize(0); + ret->ret_vec_charp.reserve(ret->ret_vec_str.size()); + std::copy(features::EnumNames::names.cbegin(), features::EnumNames::names.cend(), + std::back_inserter(ret->ret_vec_str)); + for (size_t i = 0; i < ret->ret_vec_str.size(); ++i) { + ret->ret_vec_charp.push_back(ret->ret_vec_str[i].c_str()); + } + *names = dmlc::BeginPtr(ret->ret_vec_charp); + *size = ret->ret_vec_str.size(); + API_END(); +} + int MXRandomSeed(int seed) { API_BEGIN(); mxnet::RandomSeed(seed); diff --git a/src/mxfeatures.cc b/src/mxruntime.cc similarity index 85% rename from src/mxfeatures.cc rename to src/mxruntime.cc index 7a435d7c81c9..fafe801a93c2 100644 --- a/src/mxfeatures.cc +++ b/src/mxruntime.cc @@ -19,11 +19,11 @@ /*! * Copyright (c) 2018 by Contributors - * \file mxfeatures.cc + * \file mxruntime.cc * \brief check MXNet features including compile time support */ -#include "mxnet/mxfeatures.h" +#include "mxnet/mxruntime.h" #include namespace mxnet { @@ -108,5 +108,38 @@ bool is_enabled(const unsigned feat) { return featureSet.is_enabled(feat); } +const std::vector EnumNames::names = { + "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", +}; + } // namespace features } // namespace mxnet diff --git a/tests/cpp/misc/runtime_test.cc b/tests/cpp/misc/runtime_test.cc new file mode 100644 index 000000000000..d6bb99da3683 --- /dev/null +++ b/tests/cpp/misc/runtime_test.cc @@ -0,0 +1,32 @@ +/* + * 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 + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +using namespace mxnet; +using namespace std; +using namespace mxnet::features; + +/* + * Test that different Context have different hash values + */ +TEST(RuntimeTest, RuntimeTestAll) { + EXPECT_EQ(EnumNames::names.size(), MAX_FEATURES); +} diff --git a/tests/python/unittest/test_features.py b/tests/python/unittest/test_runtime.py similarity index 84% rename from tests/python/unittest/test_features.py rename to tests/python/unittest/test_runtime.py index ff9118100e41..4e2f48a583b6 100644 --- a/tests/python/unittest/test_features.py +++ b/tests/python/unittest/test_runtime.py @@ -17,22 +17,22 @@ import mxnet as mx import sys -from mxnet.mxfeatures import * +from mxnet.runtime import * from mxnet.base import MXNetError from nose.tools import * def test_runtime_features(): for f in Feature: - res = has_feature(f.value) + res = has_feature_index(f.value) ok_(type(res) is bool) for f in features_enabled(): ok_(type(f) is Feature) - ok_(type(features_enabled_str()) is str) - print("Features enabled: {}".format(features_enabled_str())) + ok_(type(features_available()) is list) + print("Features available: {}".format(features_available())) @raises(MXNetError) def test_has_feature_2large(): - has_feature(sys.maxsize) + has_feature_index(sys.maxsize) if __name__ == "__main__": From ee462d4de8121f2666eb6ca5cf1fca95c000b29d Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 12:15:24 +0100 Subject: [PATCH 14/33] Address CR --- include/mxnet/mxruntime.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mxnet/mxruntime.h b/include/mxnet/mxruntime.h index 6a52b51a3d1a..64ff2a4d556a 100644 --- a/include/mxnet/mxruntime.h +++ b/include/mxnet/mxruntime.h @@ -33,7 +33,7 @@ *\brief whether to use opencv support */ #ifndef MXNET_USE_OPENCV -#define MXNET_USE_OPENCV 1 +#define MXNET_USE_OPENCV 0 #endif /*! From 7abd905616acdbdfde03a13b5e97719b6377bb02 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 12:17:07 +0100 Subject: [PATCH 15/33] Address CR --- tests/python/unittest/test_runtime.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/python/unittest/test_runtime.py b/tests/python/unittest/test_runtime.py index 4e2f48a583b6..e12bd3d00668 100644 --- a/tests/python/unittest/test_runtime.py +++ b/tests/python/unittest/test_runtime.py @@ -28,6 +28,8 @@ def test_runtime_features(): for f in features_enabled(): ok_(type(f) is Feature) ok_(type(features_available()) is list) + ok_(len(features_available()) > 0) + ok_(len(Feature) > 0) print("Features available: {}".format(features_available())) @raises(MXNetError) From 81c5d15493f9d987e8ca7a08598dd5ff171f5f2c Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 12:17:57 +0100 Subject: [PATCH 16/33] Address CR --- tests/cpp/misc/runtime_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpp/misc/runtime_test.cc b/tests/cpp/misc/runtime_test.cc index d6bb99da3683..147ce0ead108 100644 --- a/tests/cpp/misc/runtime_test.cc +++ b/tests/cpp/misc/runtime_test.cc @@ -25,7 +25,7 @@ using namespace std; using namespace mxnet::features; /* - * Test that different Context have different hash values + * Test that enum and string values are in sync */ TEST(RuntimeTest, RuntimeTestAll) { EXPECT_EQ(EnumNames::names.size(), MAX_FEATURES); From 4f02a6dc4a29c611cbc0437d745857cef6391746 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 12:20:31 +0100 Subject: [PATCH 17/33] Address CR --- include/mxnet/mxruntime.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mxnet/mxruntime.h b/include/mxnet/mxruntime.h index 64ff2a4d556a..7e23647e43c7 100644 --- a/include/mxnet/mxruntime.h +++ b/include/mxnet/mxruntime.h @@ -1,4 +1,4 @@ - /* +/* * 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 From ccff81181ae60d34f7e3deb2def496d068f54785 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 12:31:41 +0100 Subject: [PATCH 18/33] remove old files --- include/mxnet/mxfeatures.h | 188 ------------------------------------- src/mxfeatures.cc | 112 ---------------------- 2 files changed, 300 deletions(-) delete mode 100644 include/mxnet/mxfeatures.h delete mode 100644 src/mxfeatures.cc diff --git a/include/mxnet/mxfeatures.h b/include/mxnet/mxfeatures.h deleted file mode 100644 index 10f9b3656692..000000000000 --- a/include/mxnet/mxfeatures.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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 - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/*! - * Copyright (c) 2018 by Contributors - * \file mxfeatures.h - * \brief check MXNet features including compile time support - */ - -#pragma once - -#include "dmlc/base.h" -#include "mshadow/base.h" - -/*! - *\brief whether to use opencv support - */ -#ifndef MXNET_USE_OPENCV -#define MXNET_USE_OPENCV 1 -#endif - -/*! - *\brief whether to use cuda support - */ -#ifndef MXNET_USE_CUDA -#define MXNET_USE_CUDA MSHADOW_USE_CUDA -#endif - -/*! - *\brief whether to use cudnn library for convolution - */ -#ifndef MXNET_USE_CUDNN -#define MXNET_USE_CUDNN MSHADOW_USE_CUDNN -#endif - -#ifndef MXNET_USE_NCCL -#define MXNET_USE_NCCL 0 -#endif - -/*! - *\brief whether to use cusolver library - */ -#ifndef MXNET_USE_CUSOLVER -#define MXNET_USE_CUSOLVER MSHADOW_USE_CUSOLVER -#endif - -#ifndef MXNET_ENABLE_CUDA_RTC -#define MXNET_ENABLE_CUDA_RTC 0 -#endif - -/*! \brief Error message for using gpu when MXNET_USE_CUDA==0 */ -#define MXNET_GPU_NOT_ENABLED_ERROR "GPU is not enabled" - - -#ifndef MXNET_USE_TENSORRT -#define MXNET_USE_TENSORRT 0 -#endif - - -#ifndef MXNET_USE_BLAS_ATLAS -#define MXNET_USE_BLAS_ATLAS 0 -#endif - -#ifndef MXNET_USE_BLAS_OPEN -#define MXNET_USE_BLAS_OPEN 0 -#endif - -#ifndef MXNET_USE_BLAS_MKL -#define MXNET_USE_BLAS_MKL 0 -#endif - -#ifndef MXNET_USE_BLAS_APPLE -#define MXNET_USE_BLAS_APPLE 0 -#endif - -#ifndef MXNET_USE_LAPACK -#define MXNET_USE_LAPACK 0 -#endif - -#ifndef MXNET_USE_MKLDNN -#define MXNET_USE_MKLDNN 0 -#endif - -#ifndef MXNET_USE_OPENMP -#define MXNET_USE_OPENMP 0 -#endif - -#ifndef MXNET_USE_F16C -#define MXNET_USE_F16C MSHADOW_USE_F16C -#endif - -#ifndef MXNET_USE_CAFFE -#define MXNET_USE_CAFFE 0 -#endif - -#ifndef MXNET_USE_DIST_KVSTORE -#define MXNET_USE_DIST_KVSTORE 0 -#endif - -#ifndef MXNET_USE_SIGNAL_HANDLER -#define MXNET_USE_SIGNAL_HANDLER 0 -#endif - - - -namespace mxnet { -namespace features { -// Check compile flags such as CMakeLists.txt - -/// Compile time features -enum : uint32_t { - // NVIDIA, CUDA - CUDA = 0, - CUDNN, - NCCL, - CUDA_RTC, - TENSORRT, - - // CPU Features / optimizations - CPU_SSE, - CPU_SSE2, - CPU_SSE3, - CPU_SSE4_1, - CPU_SSE4_2, - CPU_SSE4A, // AMD extensions to SSE4 - CPU_AVX, - CPU_AVX2, - - - // Multiprocessing / CPU / System - OPENMP, - SSE, - F16C, - JEMALLOC, - - // Math libraries & BLAS - // Flavour of BLAS - BLAS_OPEN, - BLAS_ATLAS, - // Intel(R) Math Kernel Library - BLAS_MKL, - BLAS_APPLE, - // Other math libraries: - // Linear Algebra PACKage - LAPACK, - // Intel(R) Math Kernel Library for Deep Neural Networks - MKLDNN, - - // Image processing - OPENCV, - - // Misc - CAFFE, - PROFILER, - DIST_KVSTORE, - CXX14, - // Signal handler to print stack traces on exceptions - SIGNAL_HANDLER, - DEBUG, - - // size indicator - MAX_FEATURES -}; - - -/*! - * \return true if the given feature is supported - */ -bool is_enabled(uint32_t feat); - -} // namespace features -} // namespace mxnet diff --git a/src/mxfeatures.cc b/src/mxfeatures.cc deleted file mode 100644 index 7a435d7c81c9..000000000000 --- a/src/mxfeatures.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/*! - * Copyright (c) 2018 by Contributors - * \file mxfeatures.cc - * \brief check MXNet features including compile time support - */ - -#include "mxnet/mxfeatures.h" -#include - -namespace mxnet { -namespace features { - -class FeatureSet { - public: - FeatureSet() : - feature_bits() { - // GPU - feature_bits.set(CUDA, MXNET_USE_CUDA); - feature_bits.set(CUDNN, MXNET_USE_CUDNN); - feature_bits.set(NCCL, MXNET_USE_NCCL); - feature_bits.set(CUDA_RTC, MXNET_ENABLE_CUDA_RTC); - feature_bits.set(TENSORRT, MXNET_USE_TENSORRT); - - // Check flags for example with gcc -msse3 -mavx2 -dM -E - < /dev/null | egrep "SSE|AVX" -#if __SSE__ - feature_bits.set(CPU_SSE); -#endif -#if __SSE2__ - feature_bits.set(CPU_SSE2); -#endif -#if __SSE3__ - feature_bits.set(CPU_SSE3); -#endif -#if __SSE4_1__ - feature_bits.set(CPU_SSE4_1); -#endif -#if __SSE4_2__ - feature_bits.set(CPU_SSE4_2); -#endif -#if __SSE4A__ - feature_bits.set(CPU_SSE4A); -#endif -#if __AVX__ - feature_bits.set(CPU_AVX); -#endif -#if __AVX2__ - feature_bits.set(CPU_AVX2); -#endif - - // CPU - feature_bits.set(OPENMP, MXNET_USE_OPENMP); - feature_bits.set(F16C, MXNET_USE_F16C); - - // Math - feature_bits.set(BLAS_OPEN, MXNET_USE_BLAS_OPEN); - feature_bits.set(BLAS_ATLAS, MXNET_USE_BLAS_ATLAS); - feature_bits.set(BLAS_MKL, MXNET_USE_BLAS_MKL); - feature_bits.set(BLAS_APPLE, MXNET_USE_BLAS_APPLE); - feature_bits.set(LAPACK, MXNET_USE_LAPACK); - feature_bits.set(MKLDNN, MXNET_USE_MKLDNN); - - // Image - feature_bits.set(OPENCV, MXNET_USE_OPENCV); - - // Misc - feature_bits.set(CAFFE, MXNET_USE_CAFFE); - feature_bits.set(DIST_KVSTORE, MXNET_USE_DIST_KVSTORE); - feature_bits.set(SIGNAL_HANDLER, MXNET_USE_SIGNAL_HANDLER); -#ifndef NDEBUG - feature_bits.set(DEBUG); -#endif - -#if USE_JEMALLOC == 1 - feature_bits.set(JEMALLOC); -#endif - } - bool is_enabled(const unsigned feat) const { - CHECK_LT(feat, MAX_FEATURES); - return feature_bits.test(feat); - } - - private: - std::bitset feature_bits; -}; - -static FeatureSet featureSet; - -bool is_enabled(const unsigned feat) { - return featureSet.is_enabled(feat); -} - -} // namespace features -} // namespace mxnet From 23b67d124435dabd44538fd473c4428946398592 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 19:17:28 +0100 Subject: [PATCH 19/33] Fix unit test --- python/mxnet/mxfeatures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/mxfeatures.py index c546151ab06d..36f30b9ff59e 100644 --- a/python/mxnet/mxfeatures.py +++ b/python/mxnet/mxfeatures.py @@ -76,7 +76,7 @@ def has_feature(feature): True if the feature is enabled, false otherwise """ res = ctypes.c_bool() - check_call(_LIB.MXHasFeature(mx_uint(feature), ctypes.byref(res))) + check_call(_LIB.MXRuntimeHasFeature(mx_uint(feature), ctypes.byref(res))) return res.value From 375895227a0c923d26bfceb9790353d5ec30509a Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Wed, 23 Jan 2019 19:19:22 +0100 Subject: [PATCH 20/33] Port CMake blas change from #13957 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f974e8b987c..d8ef524bb389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,8 +294,8 @@ else() add_definitions(-DMXNET_USE_NCCL=0) endif() +include(cmake/ChooseBlas.cmake) if(USE_CUDA AND FIRST_CUDA) - include(cmake/ChooseBlas.cmake) include(3rdparty/mshadow/cmake/Utils.cmake) include(cmake/FirstClassLangCuda.cmake) include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) From 10e4693f889d46768f582d819a92fe95a09d2b39 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Thu, 24 Jan 2019 15:26:06 +0100 Subject: [PATCH 21/33] Fix lint --- include/mxnet/mxruntime.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mxnet/mxruntime.h b/include/mxnet/mxruntime.h index 7e23647e43c7..4be01de56a84 100644 --- a/include/mxnet/mxruntime.h +++ b/include/mxnet/mxruntime.h @@ -26,6 +26,7 @@ #pragma once #include +#include #include "dmlc/base.h" #include "mshadow/base.h" From 9949e0a8b12382317c55d0262e12bde309598a3e Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Fri, 25 Jan 2019 16:31:16 +0100 Subject: [PATCH 22/33] mxruntime -> libinfo --- include/mxnet/base.h | 2 +- include/mxnet/c_api.h | 4 +- include/mxnet/{mxruntime.h => libinfo.h} | 7 +- python/mxnet/libinfo.py | 69 +++++++++++++++- python/mxnet/runtime.py | 82 ------------------- src/c_api/c_api.cc | 6 +- src/{mxruntime.cc => libinfo.cc} | 5 +- .../misc/{runtime_test.cc => libinfo_test.cc} | 2 +- tests/python/unittest/test_libinfo.py | 26 +++++- tests/python/unittest/test_runtime.py | 42 ---------- 10 files changed, 105 insertions(+), 140 deletions(-) rename include/mxnet/{mxruntime.h => libinfo.h} (96%) delete mode 100644 python/mxnet/runtime.py rename src/{mxruntime.cc => libinfo.cc} (98%) rename tests/cpp/misc/{runtime_test.cc => libinfo_test.cc} (97%) delete mode 100644 tests/python/unittest/test_runtime.py diff --git a/include/mxnet/base.h b/include/mxnet/base.h index 14902d585a40..8f3f70432526 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -35,7 +35,7 @@ #include "nnvm/op.h" #include "nnvm/tuple.h" #include "nnvm/symbolic.h" -#include "mxruntime.h" +#include "libinfo.h" /*! diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h index aeed5c538375..f7cffae49c74 100644 --- a/include/mxnet/c_api.h +++ b/include/mxnet/c_api.h @@ -215,7 +215,7 @@ MXNET_DLL const char *MXGetLastError(); * \param out set to true if the feature is enabled, false otherwise * \return 0 when success, -1 when failure happens. */ -MXNET_DLL int MXRuntimeHasFeature(const mx_uint feature, bool *out); +MXNET_DLL int MXLibHasFeature(const mx_uint feature, bool *out); /*! * \brief Return a list of supported runtime features not enabled inclusive. @@ -223,7 +223,7 @@ MXNET_DLL int MXRuntimeHasFeature(const mx_uint feature, bool *out); * \param names ptr to array of strings containing feature names * \return 0 when success, -1 when failure happens. */ -MXNET_DLL int MXRuntimeFeatureList(size_t *size, const char ***names); +MXNET_DLL int MXLibFeatureList(size_t *size, const char ***names); /*! * \brief Seed all global random number generators in mxnet. diff --git a/include/mxnet/mxruntime.h b/include/mxnet/libinfo.h similarity index 96% rename from include/mxnet/mxruntime.h rename to include/mxnet/libinfo.h index 4be01de56a84..84f2ea96ba5d 100644 --- a/include/mxnet/mxruntime.h +++ b/include/mxnet/libinfo.h @@ -18,9 +18,10 @@ */ /*! - * Copyright (c) 2018 by Contributors - * \file mxruntime.h - * \brief check MXNet features including compile time support + * Copyright (c) 2018 by Contributors + * \file libinfo.h + * \author larroy + * \brief get features of the MXNet library at runtime */ #pragma once diff --git a/python/mxnet/libinfo.py b/python/mxnet/libinfo.py index ff795f914a4b..4a992721a1fe 100644 --- a/python/mxnet/libinfo.py +++ b/python/mxnet/libinfo.py @@ -21,6 +21,13 @@ import os import platform import logging +import ctypes +import enum +from .base import _LIB, check_call, mx_uint, py_str + + +# current version +__version__ = "1.5.0" def find_lib_path(): @@ -76,6 +83,7 @@ def find_lib_path(): os.environ['PATH'] = os.environ['PATH'] + ';' + os.path.dirname(lib_path[0]) return lib_path + def find_include_path(): """Find MXNet included header files. @@ -110,5 +118,62 @@ def find_include_path(): ' or ' + src_incl_path + '\n') -# current version -__version__ = "1.5.0" +def _feature_names_available(): + """ + + :return: + """ + feature_list = ctypes.POINTER(ctypes.c_char_p)() + feature_list_sz = ctypes.c_size_t() + check_call(_LIB.MXRuntimeFeatureList(ctypes.byref(feature_list_sz), ctypes.byref(feature_list))) + feature_names = [] + for i in range(feature_list_sz.value): + feature_names.append(py_str(feature_list[i])) + return feature_names + + +Feature = enum.Enum('Feature', {name: index for index, name in enumerate(_feature_names_available())}) + + +def features_available(): + """ + Returns + ------- + features: list of Feature enum + Features available in the backend which includes disabled and enabled ones + """ + return list(Feature) + + +def has_feature_index(feature): + """ + Check the library for compile-time feature at runtime + + Parameters + ---------- + feature : int + An integer representing the feature to check + + Returns + ------- + boolean + True if the feature is enabled, false otherwise + """ + res = ctypes.c_bool() + check_call(_LIB.MXRuntimeHasFeature(mx_uint(feature), ctypes.byref(res))) + return res.value + + +def features_enabled(): + """ + Returns + ------- + features: list of Feature enum + list of enabled features in the back-end + """ + res = [] + for f in Feature: + if has_feature_index(f.value): + res.append(f) + return res + diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py deleted file mode 100644 index f140fe4d47d7..000000000000 --- a/python/mxnet/runtime.py +++ /dev/null @@ -1,82 +0,0 @@ -# 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 -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# coding: utf-8 -# pylint: disable=not-an-iterable - -"""runtime detection of compile time features in the native library""" - -import ctypes -import enum -from .base import _LIB, check_call, mx_uint, py_str - - -def _feature_names_available(): - """ - - :return: - """ - feature_list = ctypes.POINTER(ctypes.c_char_p)() - feature_list_sz = ctypes.c_size_t() - check_call(_LIB.MXRuntimeFeatureList(ctypes.byref(feature_list_sz), ctypes.byref(feature_list))) - feature_names = [] - for i in range(feature_list_sz.value): - feature_names.append(py_str(feature_list[i])) - return feature_names - -Feature = enum.Enum('Feature', {name: index for index, name in enumerate(_feature_names_available())}) - -def features_available(): - """ - Returns - ------- - features: list of Feature enum - Features available in the backend which includes disabled and enabled ones - """ - return list(Feature) - -def has_feature_index(feature): - """ - Check the library for compile-time feature at runtime - - Parameters - ---------- - feature : int - An integer representing the feature to check - - Returns - ------- - boolean - True if the feature is enabled, false otherwise - """ - res = ctypes.c_bool() - check_call(_LIB.MXRuntimeHasFeature(mx_uint(feature), ctypes.byref(res))) - return res.value - - -def features_enabled(): - """ - Returns - ------- - features: list of Feature enum - list of enabled features in the back-end - """ - res = [] - for f in Feature: - if has_feature_index(f.value): - res.append(f) - return res diff --git a/src/c_api/c_api.cc b/src/c_api/c_api.cc index 3fec0a3a5364..76d5581b1284 100644 --- a/src/c_api/c_api.cc +++ b/src/c_api/c_api.cc @@ -43,7 +43,7 @@ #include "mxnet/kvstore.h" #include "mxnet/rtc.h" #include "mxnet/storage.h" -#include "mxnet/mxruntime.h" +#include "mxnet/libinfo.h" #include "./c_api_common.h" #include "../operator/custom/custom-inl.h" #include "../operator/tensor/matrix_op-inl.h" @@ -87,13 +87,13 @@ inline int MXAPIGetFunctionRegInfo(const FunRegType *e, // NOTE: return value is added in API_END -int MXRuntimeHasFeature(const mx_uint feature, bool *out) { +int MXLibHasFeature(const mx_uint feature, bool *out) { API_BEGIN(); *out = features::is_enabled(feature); API_END(); } -int MXRuntimeFeatureList(size_t *size, const char ***names) { +int MXLibFeatureList(size_t *size, const char ***names) { API_BEGIN(); MXAPIThreadLocalEntry *ret = MXAPIThreadLocalStore::Get(); ret->ret_vec_str.resize(0); diff --git a/src/mxruntime.cc b/src/libinfo.cc similarity index 98% rename from src/mxruntime.cc rename to src/libinfo.cc index fafe801a93c2..edef368b4511 100644 --- a/src/mxruntime.cc +++ b/src/libinfo.cc @@ -19,11 +19,12 @@ /*! * Copyright (c) 2018 by Contributors - * \file mxruntime.cc + * \file libinfo.cc + * \author larroy * \brief check MXNet features including compile time support */ -#include "mxnet/mxruntime.h" +#include "mxnet/libinfo.h" #include namespace mxnet { diff --git a/tests/cpp/misc/runtime_test.cc b/tests/cpp/misc/libinfo_test.cc similarity index 97% rename from tests/cpp/misc/runtime_test.cc rename to tests/cpp/misc/libinfo_test.cc index 147ce0ead108..594f7ac81042 100644 --- a/tests/cpp/misc/runtime_test.cc +++ b/tests/cpp/misc/libinfo_test.cc @@ -18,7 +18,7 @@ */ #include -#include +#include using namespace mxnet; using namespace std; diff --git a/tests/python/unittest/test_libinfo.py b/tests/python/unittest/test_libinfo.py index 66bf03111d4b..74b4bc3e8428 100644 --- a/tests/python/unittest/test_libinfo.py +++ b/tests/python/unittest/test_libinfo.py @@ -16,15 +16,37 @@ # under the License. import os +import sys import mxnet as mx -from mxnet import libinfo +from mxnet.libinfo import * +from mxnet.base import MXNetError +from nose.tools import * + def test_include_path(): - incl_path = libinfo.find_include_path() + incl_path = find_include_path() assert os.path.exists(incl_path) assert os.path.isdir(incl_path) +def test_runtime_features(): + for f in Feature: + res = has_feature_index(f.value) + ok_(type(res) is bool) + for f in features_enabled(): + ok_(type(f) is Feature) + ok_(type(features_available()) is list) + ok_(len(features_available()) > 0) + ok_(len(Feature) > 0) + print("Features available: {}".format(features_available())) + + +@raises(MXNetError) +def test_has_feature_2large(): + has_feature_index(sys.maxsize) + + if __name__ == '__main__': import nose nose.runmodule() + diff --git a/tests/python/unittest/test_runtime.py b/tests/python/unittest/test_runtime.py deleted file mode 100644 index e12bd3d00668..000000000000 --- a/tests/python/unittest/test_runtime.py +++ /dev/null @@ -1,42 +0,0 @@ -# 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 -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -import mxnet as mx -import sys -from mxnet.runtime import * -from mxnet.base import MXNetError -from nose.tools import * - -def test_runtime_features(): - for f in Feature: - res = has_feature_index(f.value) - ok_(type(res) is bool) - for f in features_enabled(): - ok_(type(f) is Feature) - ok_(type(features_available()) is list) - ok_(len(features_available()) > 0) - ok_(len(Feature) > 0) - print("Features available: {}".format(features_available())) - -@raises(MXNetError) -def test_has_feature_2large(): - has_feature_index(sys.maxsize) - - -if __name__ == "__main__": - import nose - nose.runmodule() From b30faf78d6987d43a0cf7034747f5c29369b5ab5 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Fri, 25 Jan 2019 16:34:39 +0100 Subject: [PATCH 23/33] Fix comments --- include/mxnet/c_api.h | 2 +- include/mxnet/libinfo.h | 2 +- python/mxnet/libinfo.py | 4 +- python/mxnet/mxfeatures.py | 103 ------------------------------------- 4 files changed, 4 insertions(+), 107 deletions(-) delete mode 100644 python/mxnet/mxfeatures.py diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h index f7cffae49c74..0f004d293793 100644 --- a/include/mxnet/c_api.h +++ b/include/mxnet/c_api.h @@ -211,7 +211,7 @@ MXNET_DLL const char *MXGetLastError(); /*! * \brief Check if a feature is enabled in the runtime - * \param feature to check mxruntime.h + * \param feature to check (see libinfo.h) * \param out set to true if the feature is enabled, false otherwise * \return 0 when success, -1 when failure happens. */ diff --git a/include/mxnet/libinfo.h b/include/mxnet/libinfo.h index 84f2ea96ba5d..2e9f34e97fdc 100644 --- a/include/mxnet/libinfo.h +++ b/include/mxnet/libinfo.h @@ -127,7 +127,7 @@ namespace features { // Check compile flags such as CMakeLists.txt /// Compile time features -// ATTENTION: When changing this enum, match the strings in mxruntime.cc!!! +// ATTENTION: When changing this enum, match the strings in the implementation file! enum : uint32_t { // NVIDIA, CUDA CUDA = 0, diff --git a/python/mxnet/libinfo.py b/python/mxnet/libinfo.py index 4a992721a1fe..41b36ce5b51a 100644 --- a/python/mxnet/libinfo.py +++ b/python/mxnet/libinfo.py @@ -125,7 +125,7 @@ def _feature_names_available(): """ feature_list = ctypes.POINTER(ctypes.c_char_p)() feature_list_sz = ctypes.c_size_t() - check_call(_LIB.MXRuntimeFeatureList(ctypes.byref(feature_list_sz), ctypes.byref(feature_list))) + check_call(_LIB.MXLibFeatureList(ctypes.byref(feature_list_sz), ctypes.byref(feature_list))) feature_names = [] for i in range(feature_list_sz.value): feature_names.append(py_str(feature_list[i])) @@ -160,7 +160,7 @@ def has_feature_index(feature): True if the feature is enabled, false otherwise """ res = ctypes.c_bool() - check_call(_LIB.MXRuntimeHasFeature(mx_uint(feature), ctypes.byref(res))) + check_call(_LIB.MXLibHasFeature(mx_uint(feature), ctypes.byref(res))) return res.value diff --git a/python/mxnet/mxfeatures.py b/python/mxnet/mxfeatures.py deleted file mode 100644 index 36f30b9ff59e..000000000000 --- a/python/mxnet/mxfeatures.py +++ /dev/null @@ -1,103 +0,0 @@ -# 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 -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# coding: utf-8 -# pylint: disable=not-an-iterable - -"""runtime detection of compile time features in the native library""" - -import ctypes -import enum -from .base import _LIB, check_call, mx_uint - -feature_names = [ - "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" -] - - -Feature = enum.Enum('Feature', {name: index for index, name in enumerate(feature_names)}) - - -def has_feature(feature): - """ - Check the library for compile-time feature at runtime - - Parameters - ---------- - feature : int - An integer representing the feature to check - - Returns - ------- - boolean - True if the feature is enabled, false otherwise - """ - res = ctypes.c_bool() - check_call(_LIB.MXRuntimeHasFeature(mx_uint(feature), ctypes.byref(res))) - return res.value - - -def features_enabled(): - """ - Returns - ------- - features: list of Feature - list of enabled features in the back-end - """ - res = [] - for f in Feature: - if has_feature(f.value): - res.append(f) - return res - -def features_enabled_str(sep=', '): - """ - Returns - ------- - string with a comma separated list of enabled features in the back-end. For example: - "CPU_SSE, OPENMP, F16C, LAPACK, MKLDNN, OPENCV, SIGNAL_HANDLER, DEBUG" - """ - return sep.join(map(lambda x: x.name, features_enabled())) From 6710cdb24ca941764edb50e32168e7f020e7a896 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Sun, 10 Feb 2019 23:03:35 +0100 Subject: [PATCH 24/33] restore libinfo.py --- python/mxnet/libinfo.py | 69 ++--------------------------------------- 1 file changed, 2 insertions(+), 67 deletions(-) diff --git a/python/mxnet/libinfo.py b/python/mxnet/libinfo.py index 41b36ce5b51a..ff795f914a4b 100644 --- a/python/mxnet/libinfo.py +++ b/python/mxnet/libinfo.py @@ -21,13 +21,6 @@ import os import platform import logging -import ctypes -import enum -from .base import _LIB, check_call, mx_uint, py_str - - -# current version -__version__ = "1.5.0" def find_lib_path(): @@ -83,7 +76,6 @@ def find_lib_path(): os.environ['PATH'] = os.environ['PATH'] + ';' + os.path.dirname(lib_path[0]) return lib_path - def find_include_path(): """Find MXNet included header files. @@ -118,62 +110,5 @@ def find_include_path(): ' or ' + src_incl_path + '\n') -def _feature_names_available(): - """ - - :return: - """ - feature_list = ctypes.POINTER(ctypes.c_char_p)() - feature_list_sz = ctypes.c_size_t() - check_call(_LIB.MXLibFeatureList(ctypes.byref(feature_list_sz), ctypes.byref(feature_list))) - feature_names = [] - for i in range(feature_list_sz.value): - feature_names.append(py_str(feature_list[i])) - return feature_names - - -Feature = enum.Enum('Feature', {name: index for index, name in enumerate(_feature_names_available())}) - - -def features_available(): - """ - Returns - ------- - features: list of Feature enum - Features available in the backend which includes disabled and enabled ones - """ - return list(Feature) - - -def has_feature_index(feature): - """ - Check the library for compile-time feature at runtime - - Parameters - ---------- - feature : int - An integer representing the feature to check - - Returns - ------- - boolean - True if the feature is enabled, false otherwise - """ - res = ctypes.c_bool() - check_call(_LIB.MXLibHasFeature(mx_uint(feature), ctypes.byref(res))) - return res.value - - -def features_enabled(): - """ - Returns - ------- - features: list of Feature enum - list of enabled features in the back-end - """ - res = [] - for f in Feature: - if has_feature_index(f.value): - res.append(f) - return res - +# current version +__version__ = "1.5.0" From 997db3e77e823d535b120f83f0b768ac6dc225d7 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 00:58:26 +0100 Subject: [PATCH 25/33] Rework API for feature detection / libinfo --- include/mxnet/base.h | 5 +++ include/mxnet/c_api.h | 22 +++++------ include/mxnet/libinfo.h | 17 ++++++++- python/mxnet/runtime.py | 38 +++++++++++++++++++ src/c_api/c_api.cc | 23 +++-------- src/c_api/c_api_profile.cc | 9 +---- src/libinfo.cc | 17 +++++++++ tests/cpp/misc/libinfo_test.cc | 1 + .../{test_libinfo.py => test_runtime.py} | 36 +++++------------- 9 files changed, 103 insertions(+), 65 deletions(-) create mode 100644 python/mxnet/runtime.py rename tests/python/unittest/{test_libinfo.py => test_runtime.py} (58%) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index 5d4faf7c1676..a753202a97db 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -403,6 +403,11 @@ template<> struct hash { return res; } }; + +template +inline std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} } #include "./tensor_blob.h" diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h index a6d7b1a86a95..e5e57c10faaa 100644 --- a/include/mxnet/c_api.h +++ b/include/mxnet/c_api.h @@ -139,6 +139,12 @@ struct MXCallbackList { void **contexts; }; +struct LibFeature { + const char* name; + uint32_t index; + bool enabled; +}; + enum CustomOpCallbacks { kCustomOpDelete, kCustomOpForward, @@ -210,20 +216,12 @@ MXNET_DLL const char *MXGetLastError(); //------------------------------------- /*! - * \brief Check if a feature is enabled in the runtime - * \param feature to check (see libinfo.h) - * \param out set to true if the feature is enabled, false otherwise - * \return 0 when success, -1 when failure happens. - */ -MXNET_DLL int MXLibHasFeature(const mx_uint feature, bool *out); - -/*! - * \brief Return a list of supported runtime features not enabled inclusive. - * \param size size of the returned array - * \param names ptr to array of strings containing feature names + * \brief Get list of features supported on the runtime + * \param libFeature pointer to array of LibFeature + * \param size of the array * \return 0 when success, -1 when failure happens. */ -MXNET_DLL int MXLibFeatureList(size_t *size, const char ***names); +MXNET_DLL int MXLibInfoFeatures(const struct LibFeature **libFeature, size_t *size); /*! * \brief Seed all global random number generators in mxnet. diff --git a/include/mxnet/libinfo.h b/include/mxnet/libinfo.h index 2e9f34e97fdc..cd9ed38ea44b 100644 --- a/include/mxnet/libinfo.h +++ b/include/mxnet/libinfo.h @@ -28,8 +28,10 @@ #include #include +#include #include "dmlc/base.h" #include "mshadow/base.h" +#include "c_api.h" /*! *\brief whether to use opencv support @@ -128,7 +130,7 @@ namespace features { /// Compile time features // ATTENTION: When changing this enum, match the strings in the implementation file! -enum : uint32_t { +enum : unsigned { // NVIDIA, CUDA CUDA = 0, CUDNN, @@ -187,10 +189,21 @@ struct EnumNames { static const std::vector names; }; +struct LibInfo { + LibInfo(); + static LibInfo* getInstance(); + const std::array& getFeatures() { + return m_lib_features; + } + private: + std::array m_lib_features; + static std::unique_ptr m_inst; +}; + /*! * \return true if the given feature is supported */ -bool is_enabled(uint32_t feat); +bool is_enabled(unsigned feat); } // namespace features } // namespace mxnet diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py new file mode 100644 index 000000000000..21cc4b33346c --- /dev/null +++ b/python/mxnet/runtime.py @@ -0,0 +1,38 @@ +# 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 +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# coding: utf-8 +# pylint: disable=not-an-iterable + +"""runtime detection of compile time features in the native library""" + +import ctypes +from .base import _LIB, check_call, mx_uint, py_str + +class LibFeature(ctypes.Structure): + _fields_ = [ + ("name", ctypes.c_char_p), + ("index", ctypes.c_uint32), + ("enabled", ctypes.c_bool) + ] + +def libinfo_features(): + 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 diff --git a/src/c_api/c_api.cc b/src/c_api/c_api.cc index 76d5581b1284..7e03acccdfae 100644 --- a/src/c_api/c_api.cc +++ b/src/c_api/c_api.cc @@ -87,25 +87,12 @@ inline int MXAPIGetFunctionRegInfo(const FunRegType *e, // NOTE: return value is added in API_END -int MXLibHasFeature(const mx_uint feature, bool *out) { +int MXLibInfoFeatures(const struct LibFeature **lib_features, size_t *size) { + using namespace features; API_BEGIN(); - *out = features::is_enabled(feature); - API_END(); -} - -int MXLibFeatureList(size_t *size, const char ***names) { - API_BEGIN(); - MXAPIThreadLocalEntry *ret = MXAPIThreadLocalStore::Get(); - ret->ret_vec_str.resize(0); - ret->ret_vec_charp.resize(0); - ret->ret_vec_charp.reserve(ret->ret_vec_str.size()); - std::copy(features::EnumNames::names.cbegin(), features::EnumNames::names.cend(), - std::back_inserter(ret->ret_vec_str)); - for (size_t i = 0; i < ret->ret_vec_str.size(); ++i) { - ret->ret_vec_charp.push_back(ret->ret_vec_str[i].c_str()); - } - *names = dmlc::BeginPtr(ret->ret_vec_charp); - *size = ret->ret_vec_str.size(); + LibInfo* lib_info = LibInfo::getInstance(); + *lib_features = lib_info->getFeatures().data(); + *size = lib_info->getFeatures().size(); API_END(); } diff --git a/src/c_api/c_api_profile.cc b/src/c_api/c_api_profile.cc index dc1b7810147f..c062458cc384 100644 --- a/src/c_api/c_api_profile.cc +++ b/src/c_api/c_api_profile.cc @@ -52,11 +52,6 @@ struct APICallTimingData { #endif // PROFILE_API_INCLUDE_AS_EVENT }; -template -inline std::unique_ptr make_unique(Args&&... args) { - return std::unique_ptr(new T(std::forward(args)...)); -} - /*! * \brief Per-thread profiling data */ @@ -78,7 +73,7 @@ class ProfilingThreadData { auto iter = tasks_.find(name); if (iter == tasks_.end()) { iter = tasks_.emplace(std::make_pair( - name, make_unique(name, domain))).first; + name, std::make_unique(name, domain))).first; } return iter->second.get(); } @@ -93,7 +88,7 @@ class ProfilingThreadData { // Per-thread so no lock necessary auto iter = events_.find(name); if (iter == events_.end()) { - iter = events_.emplace(std::make_pair(name, make_unique(name))).first; + iter = events_.emplace(std::make_pair(name, std::make_unique(name))).first; } return iter->second.get(); } diff --git a/src/libinfo.cc b/src/libinfo.cc index edef368b4511..44a834c85b16 100644 --- a/src/libinfo.cc +++ b/src/libinfo.cc @@ -26,6 +26,7 @@ #include "mxnet/libinfo.h" #include +#include "mxnet/base.h" namespace mxnet { namespace features { @@ -109,6 +110,22 @@ bool is_enabled(const unsigned feat) { return featureSet.is_enabled(feat); } +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; + } +} + +LibInfo *LibInfo::getInstance() { + if (!m_inst) + m_inst = std::make_unique(); + return m_inst.get(); +} + +std::unique_ptr LibInfo::m_inst = nullptr; + const std::vector EnumNames::names = { "CUDA", "CUDNN", diff --git a/tests/cpp/misc/libinfo_test.cc b/tests/cpp/misc/libinfo_test.cc index 594f7ac81042..57f8f8d764c3 100644 --- a/tests/cpp/misc/libinfo_test.cc +++ b/tests/cpp/misc/libinfo_test.cc @@ -29,4 +29,5 @@ using namespace mxnet::features; */ TEST(RuntimeTest, RuntimeTestAll) { EXPECT_EQ(EnumNames::names.size(), MAX_FEATURES); + const auto& features = LibInfo::getInstance()->getFeatures(); } diff --git a/tests/python/unittest/test_libinfo.py b/tests/python/unittest/test_runtime.py similarity index 58% rename from tests/python/unittest/test_libinfo.py rename to tests/python/unittest/test_runtime.py index 74b4bc3e8428..433301819252 100644 --- a/tests/python/unittest/test_libinfo.py +++ b/tests/python/unittest/test_runtime.py @@ -15,38 +15,22 @@ # specific language governing permissions and limitations # under the License. -import os -import sys import mxnet as mx -from mxnet.libinfo import * +import sys +from mxnet.runtime import * 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_include_path(): - incl_path = find_include_path() - assert os.path.exists(incl_path) - assert os.path.isdir(incl_path) - - -def test_runtime_features(): - for f in Feature: - res = has_feature_index(f.value) - ok_(type(res) is bool) - for f in features_enabled(): - ok_(type(f) is Feature) - ok_(type(features_available()) is list) - ok_(len(features_available()) > 0) - ok_(len(Feature) > 0) - print("Features available: {}".format(features_available())) -@raises(MXNetError) -def test_has_feature_2large(): - has_feature_index(sys.maxsize) - - -if __name__ == '__main__': +if __name__ == "__main__": import nose nose.runmodule() - From c7a348e5f783abefd04578532fee9e09d483b70c Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 11:50:25 +0100 Subject: [PATCH 26/33] Refine documentation --- python/mxnet/runtime.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/python/mxnet/runtime.py b/python/mxnet/runtime.py index 21cc4b33346c..afb393281420 100644 --- a/python/mxnet/runtime.py +++ b/python/mxnet/runtime.py @@ -18,12 +18,15 @@ # coding: utf-8 # pylint: disable=not-an-iterable -"""runtime detection of compile time features in the native library""" +"""runtime querying of compile time features in the native library""" import ctypes -from .base import _LIB, check_call, mx_uint, py_str +from .base import _LIB, check_call class LibFeature(ctypes.Structure): + """ + Compile time feature description + """ _fields_ = [ ("name", ctypes.c_char_p), ("index", ctypes.c_uint32), @@ -31,6 +34,13 @@ class LibFeature(ctypes.Structure): ] def libinfo_features(): + """ + Check the library for compile-time features. The list of features are maintained in libinfo.h and libinfo.cc + + Returns + ------- + A 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))) From 3da28d76fed98f03b10bcdf483d59a129916c402 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 11:54:12 +0100 Subject: [PATCH 27/33] Fix lint --- include/mxnet/base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index a753202a97db..e1b1a772c5f7 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -408,7 +408,7 @@ template inline std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } -} +} // namespace std #include "./tensor_blob.h" //! \endcond From 615b051b1b6dae30cc72022d8f680d07c80eb809 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 12:57:31 +0100 Subject: [PATCH 28/33] Fix lint --- src/c_api/c_api_profile.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/c_api/c_api_profile.cc b/src/c_api/c_api_profile.cc index c062458cc384..0de7b485531c 100644 --- a/src/c_api/c_api_profile.cc +++ b/src/c_api/c_api_profile.cc @@ -88,7 +88,8 @@ class ProfilingThreadData { // Per-thread so no lock necessary auto iter = events_.find(name); if (iter == events_.end()) { - iter = events_.emplace(std::make_pair(name, std::make_unique(name))).first; + iter = events_.emplace(std::make_pair(name, + std::make_unique(name))).first; } return iter->second.get(); } From d897ef0420f999cbd8a99de5b69a858220775cf4 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 13:54:27 +0100 Subject: [PATCH 29/33] Define make_unique only for C++ std < 14 --- include/mxnet/base.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index e1b1a772c5f7..364d957ca865 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -404,10 +404,12 @@ template<> struct hash { } }; +#if __cplusplus < 201402L template inline std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } +#endif } // namespace std #include "./tensor_blob.h" From e3be970866a44dc646af1e1fee7a59dbaa702266 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 19:41:07 +0000 Subject: [PATCH 30/33] Add memory include --- include/mxnet/libinfo.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mxnet/libinfo.h b/include/mxnet/libinfo.h index cd9ed38ea44b..f35d41a9aa8a 100644 --- a/include/mxnet/libinfo.h +++ b/include/mxnet/libinfo.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "dmlc/base.h" #include "mshadow/base.h" #include "c_api.h" From 683f1cc29fcf48e493d7dcb7a385844116b6a911 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 22:22:40 +0100 Subject: [PATCH 31/33] remove old tests --- tests/python/unittest/test_features.py | 40 -------------------------- 1 file changed, 40 deletions(-) delete mode 100644 tests/python/unittest/test_features.py diff --git a/tests/python/unittest/test_features.py b/tests/python/unittest/test_features.py deleted file mode 100644 index ff9118100e41..000000000000 --- a/tests/python/unittest/test_features.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -import mxnet as mx -import sys -from mxnet.mxfeatures import * -from mxnet.base import MXNetError -from nose.tools import * - -def test_runtime_features(): - for f in Feature: - res = has_feature(f.value) - ok_(type(res) is bool) - for f in features_enabled(): - ok_(type(f) is Feature) - ok_(type(features_enabled_str()) is str) - print("Features enabled: {}".format(features_enabled_str())) - -@raises(MXNetError) -def test_has_feature_2large(): - has_feature(sys.maxsize) - - -if __name__ == "__main__": - import nose - nose.runmodule() From 8fa05a1ddb8b707575dfa3a9d2e33d13a957f205 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 22:24:43 +0100 Subject: [PATCH 32/33] make_unique fiasco --- include/mxnet/base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index 364d957ca865..ec87e6ec71b0 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -404,7 +404,7 @@ template<> struct hash { } }; -#if __cplusplus < 201402L +#if __cplusplus < 201402L && ! defined(_MSC_VER) template inline std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); From f6f53567c33bb4f027f47593ba057913c20969f7 Mon Sep 17 00:00:00 2001 From: Pedro Larroy Date: Mon, 11 Feb 2019 22:37:19 +0100 Subject: [PATCH 33/33] Fix lint --- include/mxnet/base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mxnet/base.h b/include/mxnet/base.h index ec87e6ec71b0..26c1a1bd2b29 100644 --- a/include/mxnet/base.h +++ b/include/mxnet/base.h @@ -404,7 +404,7 @@ template<> struct hash { } }; -#if __cplusplus < 201402L && ! defined(_MSC_VER) +#if __cplusplus < 201402L && !defined(_MSC_VER) template inline std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...));