From ca31f9a4bc862b928d25ce5e822f39ade017b877 Mon Sep 17 00:00:00 2001 From: "Martin T. H. Sandsmark" Date: Sun, 4 Mar 2018 13:46:29 +0100 Subject: [PATCH 1/2] port to c++11 --- CMakeLists.txt | 8 +---- README.md | 4 +-- debian/control | 6 ++-- examples/CMakeLists.txt | 4 +-- experimental/kdtree_cpu.cpp | 2 -- nabo/kdtree_cpu.cpp | 13 ++++--- nabo/kdtree_opencl.cpp | 15 ++++---- nabo/nabo.h | 4 +-- nabo/nabo_private.h | 8 ++--- tests/CMakeLists.txt | 17 ++++----- tests/helpers.h | 69 ++++++++----------------------------- tests/knnbench.cpp | 10 +++--- tests/knnbucketsize.cpp | 2 +- tests/knnepsilon.cpp | 2 +- 14 files changed, 51 insertions(+), 113 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75ec5f4..442328e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,12 +83,6 @@ else () set (CMAKE_CXX_STANDARD 11) endif () -# Boost required for any and cstdint on MSVC < 2010 -find_package(Boost COMPONENTS REQUIRED) -if(MSVC AND (MSVC_VERSION LESS 1600)) - add_definitions(-DBOOST_STDINT) -endif(MSVC AND (MSVC_VERSION LESS 1600)) - # openmp set(USE_OPEN_MP TRUE CACHE BOOL "Set to FALSE to not use OpenMP") if (USE_OPEN_MP) @@ -143,7 +137,7 @@ else (USE_OPEN_CL) endif (USE_OPEN_CL) # include all libs so far -include_directories(${CMAKE_SOURCE_DIR} ${EIGEN_INCLUDE_DIR} ${Boost_INCLUDE_DIRS}) +include_directories(${CMAKE_SOURCE_DIR} ${EIGEN_INCLUDE_DIR}) # main nabo lib set(NABO_SRC diff --git a/README.md b/README.md index 976cf85..3fd4342 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ On the average, libnabo is 5% to 20% faster than [ANN]. libnabo depends on [Eigen], a modern C++ matrix and linear-algebra library. libnabo works with either version 2 or 3 of Eigen. -libnabo also depends on [Boost], a C++ general library. +libnabo also optionally depends on [Boost], a C++ general library, for Python bindings. libnabo was developed by [Stéphane Magnenat](http://stephane.magnenat.net) as part of his work at [ASL-ETH](http://www.asl.ethz.ch) and is now maintained by [Simon Lynen](https://github.com/simonlynen). @@ -30,7 +30,7 @@ You will find a nice introductory tutorial in [this video](http://www.youtube.co Prerequisites ------------- -If your operating system does not provide it, you must get [Eigen] and [Boost]. +If your operating system does not provide it, you must get [Eigen], and [Boost] if you want to build the Python bindings. [Eigen] only needs to be downloaded and extracted. You also need `grep`, which is available in standard on Linux or Mac OS X, you can get the window version [here](http://gnuwin32.sourceforge.net/packages/grep.htm). diff --git a/debian/control b/debian/control index c1138e4..5196022 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: libnabo Priority: extra Maintainer: Stéphane Magnenat -Build-Depends: debhelper (>= 7.0.50~), cmake, doxygen, cdbs, libboost-dev, libboost-python-dev, libeigen3-dev, python-dev, python-numpy +Build-Depends: debhelper (>= 7.0.50~), cmake, doxygen, cdbs, libboost-python-dev, libeigen3-dev, python-dev, python-numpy Standards-Version: 3.9.1 Section: libs Homepage: https://github.com/ethz-asl/libnabo @@ -11,7 +11,7 @@ Vcs-Browser: https://github.com/ethz-asl/libnabo Package: libnabo-dev Section: libdevel Architecture: any -Depends: libnabo1 (= ${binary:Version}), libboost-dev, libeigen3-dev +Depends: libnabo1 (= ${binary:Version}), libeigen3-dev Suggests: libnabo-doc Description: Development headers of libnabo, a fast K Nearset Neighbor library. libnabo is a fast K Nearest Neighbour library for low-dimensional spaces. @@ -62,4 +62,4 @@ Description: Python bindings for libnabo, a fast K Nearset Neighbor library. It provides a clean, legacy-free, scalar-type–agnostic API thanks to C++ templates. Its current CPU implementation is strongly inspired by ANN, but with more compact data types. On the average, libnabo is 5% to 20% - faster than ANN. \ No newline at end of file + faster than ANN. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 348bd65..77708a0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,7 @@ include_directories(..) add_executable(trivial trivial.cpp) -target_link_libraries(trivial ${LIB_NAME} ${EXTRA_LIBS} ${Boost_LIBRARIES}) +target_link_libraries(trivial ${LIB_NAME} ${EXTRA_LIBS}) add_executable(usage usage.cpp) -target_link_libraries(usage ${LIB_NAME} ${EXTRA_LIBS} ${Boost_LIBRARIES}) \ No newline at end of file +target_link_libraries(usage ${LIB_NAME} ${EXTRA_LIBS}) diff --git a/experimental/kdtree_cpu.cpp b/experimental/kdtree_cpu.cpp index f5c89ca..302b672 100644 --- a/experimental/kdtree_cpu.cpp +++ b/experimental/kdtree_cpu.cpp @@ -36,8 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include -#include namespace Nabo { diff --git a/nabo/kdtree_cpu.cpp b/nabo/kdtree_cpu.cpp index 5b5fb4e..cb1f8d1 100644 --- a/nabo/kdtree_cpu.cpp +++ b/nabo/kdtree_cpu.cpp @@ -37,9 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include -#include -#include #ifdef HAVE_OPENMP #include #endif @@ -96,8 +93,8 @@ namespace Nabo template pair KDTreeUnbalancedPtInLeavesImplicitBoundsStackOpt::getBounds(const BuildPointsIt first, const BuildPointsIt last, const unsigned dim) { - T minVal(boost::numeric::bounds::highest()); - T maxVal(boost::numeric::bounds::lowest()); + T minVal(std::numeric_limits::max()); + T maxVal(std::numeric_limits::lowest()); for (BuildPointsCstIt it(first); it != last; ++it) { @@ -235,7 +232,7 @@ namespace Nabo dimMask((1< maxNodeCount) { - throw runtime_error((boost::format("Cloud has a risk to have more nodes (%1%) than the kd-tree allows (%2%). The kd-tree has %3% bits for dimensions and %4% bits for node indices") % estimatedNodeCount % maxNodeCount % dimBitCount % (32-dimBitCount)).str()); + throw runtime_error("Cloud has a risk to have more nodes (" + std::to_string(estimatedNodeCount) + ") than the kd-tree allows (" + std::to_string(maxNodeCount) + "). " + "The kd-tree has " + std::to_string(dimBitCount) + " bits for dimensions and " + std::to_string((32-dimBitCount)) + " bits for node indices"); } // build point vector and compute bounds @@ -465,3 +463,4 @@ namespace Nabo //@} } +/* vim: set ts=8 sw=8 tw=0 noexpandtab cindent softtabstop=8 :*/ diff --git a/nabo/kdtree_opencl.cpp b/nabo/kdtree_opencl.cpp index 1011185..5a9fee2 100644 --- a/nabo/kdtree_opencl.cpp +++ b/nabo/kdtree_opencl.cpp @@ -41,10 +41,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include // #include -#include -#include -#include -#include /*! \file kdtree_opencl.cpp @@ -203,7 +199,7 @@ namespace Nabo //! Create a new contexc for a given type of device cl::Context& createContext(const cl_device_type deviceType) { - boost::mutex::scoped_lock lock(mutex); + std::lock_guard lock(mutex); Devices::iterator it(devices.find(deviceType)); if (it == devices.end()) { @@ -216,7 +212,7 @@ namespace Nabo //! Return the cache for a given type of device SourceCacher* getSourceCacher(const cl_device_type deviceType) { - boost::mutex::scoped_lock lock(mutex); + std::lock_guard lock(mutex); Devices::iterator it(devices.find(deviceType)); if (it == devices.end()) throw runtime_error("Attempt to get source cacher before creating a context"); @@ -225,7 +221,7 @@ namespace Nabo protected: Devices devices; //!< devices with caches - boost::mutex mutex; //!< mutex to protect concurrent accesses to devices + std::mutex mutex; //!< mutex to protect concurrent accesses to devices }; //! Static instance of context manager @@ -545,7 +541,7 @@ namespace Nabo const unsigned maxStackDepth(getTreeDepth(nodes.size()) + 1); // init openCL - initOpenCL("knn_kdtree_pt_in_leaves.cl", "knnKDTree", (boost::format("#define MAX_STACK_DEPTH %1%\n") % maxStackDepth).str()); + initOpenCL("knn_kdtree_pt_in_leaves.cl", "knnKDTree", "#define MAX_STACK_DEPTH " + std::to_string(maxStackDepth) + "\n"); // map nodes, for info about alignment, see sect 6.1.5 const size_t nodesCLSize(nodes.size() * sizeof(Node)); @@ -672,7 +668,7 @@ namespace Nabo const unsigned maxStackDepth(getTreeDepth(nodes.size()) + 1); // init openCL - initOpenCL("knn_kdtree_pt_in_nodes.cl", "knnKDTree", (boost::format("#define MAX_STACK_DEPTH %1%\n") % maxStackDepth).str()); + initOpenCL("knn_kdtree_pt_in_nodes.cl", "knnKDTree", "#define MAX_STACK_DEPTH " + std::to_string(maxStackDepth) + "\n"); // map nodes, for info about alignment, see sect 6.1.5 const size_t nodesCLSize(nodes.size() * sizeof(Node)); @@ -694,3 +690,4 @@ namespace Nabo } #endif // HAVE_OPENCL +/* vim: set ts=8 sw=8 tw=0 noexpandtab cindent softtabstop=8 :*/ diff --git a/nabo/nabo.h b/nabo/nabo.h index 8358121..46576a1 100644 --- a/nabo/nabo.h +++ b/nabo/nabo.h @@ -62,7 +62,6 @@ On the average, libnabo is 5% to 20% faster than \ref ANN. libnabo depends on \ref Eigen, a modern C++ matrix and linear-algebra library. libnabo works with either version 2 or 3 of Eigen. -libnabo also depends on \ref Boost, a C++ general library. \section Compilation @@ -192,14 +191,13 @@ libnabo differs from \ref ANN on the following points: * performances - about 5% to 20% faster than ANN (both -O3 -NDEBUG), probably due to the smaller memory footprint -- clearly memory-bound, neither OpenMP nor boost::thread improve performances +- clearly memory-bound, neither OpenMP nor std::thread improve performances \section References \li \anchor Eigen Eigen: http://eigen.tuxfamily.org \li \anchor ANN ANN: http://www.cs.umd.edu/~mount/ANN \li \anchor CMake CMake: http://www.cmake.org -\li \anchor Boost Boost: http://www.boost.org */ diff --git a/nabo/nabo_private.h b/nabo/nabo_private.h index c414422..a830b99 100644 --- a/nabo/nabo_private.h +++ b/nabo/nabo_private.h @@ -34,12 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "nabo.h" -#ifdef BOOST_STDINT - #include - using boost::uint32_t; -#else // BOOST_STDINT - #include -#endif // BOOST_STDINT +#include +using std::uint32_t; // OpenCL #ifdef HAVE_OPENCL diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e0d81be..be1b65d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,8 +3,8 @@ include (CheckSymbolExists) include_directories(..) add_executable(knnvalidate knnvalidate.cpp) -target_link_libraries(knnvalidate ${LIB_NAME} ${EXTRA_LIBS} ${Boost_LIBRARIES}) -# disable as experimental is broken target_link_libraries(knnvalidate naboexperimental nabo ${EXTRA_LIBS} ${Boost_LIBRARIES}) +target_link_libraries(knnvalidate ${LIB_NAME} ${EXTRA_LIBS}) +# disable as experimental is broken target_link_libraries(knnvalidate naboexperimental nabo ${EXTRA_LIBS}) add_test(validation-2D-exhaustive ${EXECUTABLE_OUTPUT_PATH}/knnvalidate ${CMAKE_CURRENT_SOURCE_DIR}/data/scan.2d.txt 10 2 -1) add_test(validation-2D-random ${EXECUTABLE_OUTPUT_PATH}/knnvalidate ${CMAKE_CURRENT_SOURCE_DIR}/data/scan.2d.txt 10 2 10000) @@ -51,16 +51,11 @@ else (FLANN_INCLUDE_DIR AND FLANN_LIBRARY) message("FLANN not found, disabling it in benchmarks") endif (FLANN_INCLUDE_DIR AND FLANN_LIBRARY) -check_symbol_exists(_POSIX_TIMERS "unistd.h;time.h" POSIX_TIMERS) -if (POSIX_TIMERS AND NOT APPLE) - set(EXTRA_LIBS ${EXTRA_LIBS} rt) -endif (POSIX_TIMERS AND NOT APPLE) - include_directories(..) add_executable(knnbench knnbench.cpp) -target_link_libraries(knnbench ${LIB_NAME} ${EXTRA_LIBS} ${Boost_LIBRARIES}) -# disable as experimental is broken target_link_libraries(knnbench naboexperimental nabo ${EXTRA_LIBS} ${Boost_LIBRARIES}) +target_link_libraries(knnbench ${LIB_NAME} ${EXTRA_LIBS}) +# disable as experimental is broken target_link_libraries(knnbench naboexperimental nabo ${EXTRA_LIBS}) add_test(bench-3D-large-exhaustive-10000-K1 ${EXECUTABLE_OUTPUT_PATH}/knnbench ${CMAKE_CURRENT_SOURCE_DIR}/data/scan.3d.large.txt 1 -10000 3 5) add_test(bench-3D-large-exhaustive-1000-K1 ${EXECUTABLE_OUTPUT_PATH}/knnbench ${CMAKE_CURRENT_SOURCE_DIR}/data/scan.3d.large.txt 1 -1000 3 5) @@ -76,10 +71,10 @@ add_test(bench-3D-large-exhaustive-100-K30 ${EXECUTABLE_OUTPUT_PATH}/knnbench ${ add_test(bench-3D-large-random-K30 ${EXECUTABLE_OUTPUT_PATH}/knnbench ${CMAKE_CURRENT_SOURCE_DIR}/data/scan.3d.large.txt 30 40000 3 5) add_executable(knnepsilon knnepsilon.cpp) -target_link_libraries(knnepsilon ${LIB_NAME} ${EXTRA_LIBS} ${Boost_LIBRARIES}) +target_link_libraries(knnepsilon ${LIB_NAME} ${EXTRA_LIBS}) add_executable(knnbucketsize knnbucketsize.cpp) -target_link_libraries(knnbucketsize ${LIB_NAME} ${EXTRA_LIBS} ${Boost_LIBRARIES}) +target_link_libraries(knnbucketsize ${LIB_NAME} ${EXTRA_LIBS}) # Ensure that users cannot instantiate a tree with wrong matrix types. macro(try_compile_cloud_types MAT_TYPE TREE_TYPE EXPECT) diff --git a/tests/helpers.h b/tests/helpers.h index ffc9f32..115b775 100644 --- a/tests/helpers.h +++ b/tests/helpers.h @@ -37,12 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#ifdef BOOST_STDINT - #include - using boost::uint64_t; -#else // BOOST_STDINT - #include -#endif // BOOST_STDINT +#include +using std::uint64_t; using namespace std; using namespace Nabo; @@ -129,55 +125,20 @@ typename NearestNeighbourSearch::Matrix createQuery(const typename NearestNei return q; } -#ifdef __MACH__ -#include -#include -#else -#include -#endif - -#ifdef _POSIX_TIMERS -namespace boost +#include +using std::chrono::high_resolution_clock; +using std::chrono::duration_cast; +struct timer { - /* - High-precision timer class, using gettimeofday(). - The interface is a subset of the one boost::timer provides, - but the implementation is much more precise - on systems where clock() has low precision, such as glibc. - */ - struct timer - { - typedef uint64_t Time; - - timer():_start_time(curTime()){ } - void restart() { _start_time = curTime(); } - double elapsed() const // return elapsed time in seconds - { return double(curTime() - _start_time) / double(1000000000); } - - private: - Time curTime() const { - #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t ts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &ts); - mach_port_deallocate(mach_task_self(), cclock); - #else - struct timespec ts; - #ifdef CLOCK_PROCESS_CPUTIME_ID - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); - #else // BSD and old Linux - clock_gettime(CLOCK_PROF, &ts); - #endif - #endif - return Time(ts.tv_sec) * Time(1000000000) + Time(ts.tv_nsec); - } - Time _start_time; - }; -} -#else // _POSIX_TIMERS - #include -#endif // _POSIX_TIMERS + timer():_start_time(high_resolution_clock::now()){ } + void restart() { _start_time = high_resolution_clock::now(); } + double elapsed() const // return elapsed time in seconds + { return duration_cast(high_resolution_clock::now() - _start_time).count() / double(1000000000); } + +private: + high_resolution_clock::time_point _start_time; +}; #endif // __NABE_TEST_HELPERS_H +/* vim: set ts=8 sw=8 tw=0 noexpandtab cindent softtabstop=8 :*/ diff --git a/tests/knnbench.cpp b/tests/knnbench.cpp index b8a8c75..d56c95a 100644 --- a/tests/knnbench.cpp +++ b/tests/knnbench.cpp @@ -117,7 +117,7 @@ typedef vector BenchResults; // BenchResult doBench(const Matrix& d, const Matrix& q, const Index K, const int itCount) // { // BenchResult result; -// boost::timer t; +// timer t; // T nns(d); // result.creationDuration = t.elapsed(); // @@ -145,7 +145,7 @@ BenchResult doBenchType(const typename NearestNeighbourSearch::SearchType typ typedef typename NearestNeighbourSearch::IndexMatrix IndexMatrix; BenchResult result; - boost::timer t; + timer t; nnsT* nns(nnsT::create(d, d.rows(), type, creationOptionFlags)); result.creationDuration = t.elapsed(); @@ -173,7 +173,7 @@ BenchResult doBenchType(const typename NearestNeighbourSearch::SearchType typ BenchResult doBenchANNStack(const MatrixD& d, const MatrixD& q, const int K, const int itCount, const int searchCount) { BenchResult result; - boost::timer t; + timer t; const int ptCount(d.cols()); const double **pa = new const double *[d.cols()]; for (int i = 0; i < ptCount; ++i) @@ -207,7 +207,7 @@ BenchResult doBenchANNStack(const MatrixD& d, const MatrixD& q, const int K, con BenchResult doBenchANNPriority(const MatrixD& d, const MatrixD& q, const int K, const int itCount, const int searchCount) { BenchResult result; - boost::timer t; + timer t; const int ptCount(d.cols()); const double **pa = new const double *[d.cols()]; for (int i = 0; i < ptCount; ++i) @@ -263,7 +263,7 @@ BenchResult doBenchFLANN(const Matrix& d, const Matrix& q, const Index K, const flann::Matrix dists(new float[query.rows*K], query.rows, K); // construct an randomized kd-tree index using 4 kd-trees - boost::timer t; + timer t; flann::Index index(dataset, flann::KDTreeIndexParams(4) /*flann::AutotunedIndexParams(0.9)*/); // exact search index.buildIndex(); result.creationDuration = t.elapsed(); diff --git a/tests/knnbucketsize.cpp b/tests/knnbucketsize.cpp index 2cb3a04..976f6d1 100644 --- a/tests/knnbucketsize.cpp +++ b/tests/knnbucketsize.cpp @@ -69,7 +69,7 @@ void doTestEpsilon(const char *fileName, const int K, const int method, const in double duration(0); for (int s = 0; s < searchCount; ++s) { - boost::timer t; + timer t; nns->knn(q, indexes_bf, dists2_bf, K, 0, NNS::ALLOW_SELF_MATCH); duration += t.elapsed(); } diff --git a/tests/knnepsilon.cpp b/tests/knnepsilon.cpp index cc7beda..eec5497 100644 --- a/tests/knnepsilon.cpp +++ b/tests/knnepsilon.cpp @@ -68,7 +68,7 @@ void doTestEpsilon(const char *fileName, const int K, const int method, const in double touchStats(0); for (int s = 0; s < searchCount; ++s) { - boost::timer t; + timer t; touchStats += nns->knn(q, indexes_bf, dists2_bf, K, epsilon, NNS::ALLOW_SELF_MATCH); duration += t.elapsed(); } From 2a965e8cba53bf918d0e4805f5b76751dbbb0cb0 Mon Sep 17 00:00:00 2001 From: HannesSommer Date: Wed, 18 Apr 2018 17:39:12 +0200 Subject: [PATCH 2/2] Minor cleanups as suggested for #89. --- tests/helpers.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/helpers.h b/tests/helpers.h index 115b775..cc47986 100644 --- a/tests/helpers.h +++ b/tests/helpers.h @@ -33,12 +33,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define __NABE_TEST_HELPERS_H #include "nabo/nabo.h" +#include #include #include #include #include -using std::uint64_t; using namespace std; using namespace Nabo; @@ -125,18 +125,24 @@ typename NearestNeighbourSearch::Matrix createQuery(const typename NearestNei return q; } -#include -using std::chrono::high_resolution_clock; -using std::chrono::duration_cast; struct timer { - timer():_start_time(high_resolution_clock::now()){ } - void restart() { _start_time = high_resolution_clock::now(); } + using Clock = std::chrono::high_resolution_clock; + using Time = Clock::time_point; + + timer():_start_time(curTime()){ } + void restart() { _start_time = curTime(); } double elapsed() const // return elapsed time in seconds - { return duration_cast(high_resolution_clock::now() - _start_time).count() / double(1000000000); } + { + using namespace std::chrono; + return duration_cast>(curTime() - _start_time).count(); + } private: - high_resolution_clock::time_point _start_time; + Time curTime() const { + return Clock::now(); + } + Time _start_time; }; #endif // __NABE_TEST_HELPERS_H