diff --git a/README.md b/README.md index f3356fc..6da3e12 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A drop-in header-only C++ library to detect hardware capabilities at runtime and You have 2 options: -1. you can just copy the contents of `include` into your project and off you go +1. you can just copy the contents of `single_include` (or `include` if you like to have multiple folders and source code files) into your project and off you go 2. you use the cmake build infrastructure to put compass in a desired folder @@ -22,17 +22,17 @@ You have 2 options: $ make install #depending on the contents of CMAKE_INSTALL_PREFIX, you may use sudo ``` - - on Windows platforms (assuming that `cmake` and `boost\lib` are in your `PATH`) + - on Windows platforms (assuming that `cmake` is in your `PATH`) ``` > cd repo > mkdir build > cd build - > cmake.exe -G "Visual Studio 14 2015 Win64" -DBOOST_ROOT=C:\path\to\boost\1_59_0 .. + > cmake.exe -G "Visual Studio 14 2015 Win64" .. > cmake.exe --build . --target ALL_BUILD --config Release > ctest.exe -C Release ``` -(3.) tests can only be run if you have access to the test machines and it requires boost to be installed (if boost is not detected, the tests are skipped and a warning is issued) +(3.) tests should only be run on the hardware where `cmake` was called. `CMakeLists.txt` is trying hard to detect the hardware features at `cmake` invocation. They are then included in the unit test suite. ## Compass API @@ -65,14 +65,13 @@ This project is quite small, so here is your chance to boost open-source to the - [ ] code review the model to extend compass for new compilers/platforms/OSes - [ ] code review the model to extend compass for new features -- [ ] contribute adding detection of the cache hierarchy and associated cache sizes on x86 - [ ] is thread-safety an issue of the current implementation ? - [ ] contribute for adding Intel compiler on x86 - [ ] contribute for GPUs (nvcc) - [ ] extend support for OpenPower (gcc) - [ ] contribute for ARM (gcc/clang) if you have according hardware available -A good place to start and to see what is needed, is llvm [`Host.cpp`](http://llvm.org/docs/doxygen/html/Host_8cpp_source.html) file +A good place to start and to see what is needed, is llvm [`Host.cpp`](http://llvm.org/docs/doxygen/html/Host_8cpp_source.html) file. ## License diff --git a/include/detail/api.hpp b/include/detail/api.hpp index a3ad4e6..9f279cc 100644 --- a/include/detail/api.hpp +++ b/include/detail/api.hpp @@ -58,6 +58,40 @@ namespace compass { } + + namespace detail { + + static std::uint32_t accumulate(std::uint32_t value){ + return value; + } + + template < typename T, typename... features_t > + static std::uint32_t accumulate(std::uint32_t value, + T head, + features_t... tail) + { + + std::uint32_t local = compass::runtime::has(head); + value = (value <<= 1) | local; + + return accumulate(value,tail...); + + } + + }; + + + template + static std::uint32_t accumulate(feature_t... features) { + + static const int pack_size = sizeof...(features); + static_assert(pack_size <= 32, "[compass::runtime::accumulate] unable to handle more than 32 features" ); + + std::uint32_t value = compass::runtime::detail::accumulate( 0u, features...); + return value; + + } + namespace size { struct cacheline{ diff --git a/single_include/compass.hpp b/single_include/compass.hpp index 94f8efa..768fc0c 100644 --- a/single_include/compass.hpp +++ b/single_include/compass.hpp @@ -1116,6 +1116,40 @@ namespace compass { } + + namespace detail { + + static std::uint32_t accumulate(std::uint32_t value){ + return value; + } + + template < typename T, typename... features_t > + static std::uint32_t accumulate(std::uint32_t value, + T head, + features_t... tail) + { + + std::uint32_t local = compass::runtime::has(head); + value = (value <<= 1) | local; + + return accumulate(value,tail...); + + } + + }; + + + template + static std::uint32_t accumulate(feature_t... features) { + + static const int pack_size = sizeof...(features); + static_assert(pack_size <= 32, "[compass::runtime::accumulate] unable to handle more than 32 features" ); + + std::uint32_t value = compass::runtime::detail::accumulate( 0u, features...); + return value; + + } + namespace size { struct cacheline{ diff --git a/tests/test_build_machine.cpp b/tests/test_build_machine.cpp index 8eb8b9b..449bebc 100644 --- a/tests/test_build_machine.cpp +++ b/tests/test_build_machine.cpp @@ -3,6 +3,7 @@ #include "compass.hpp" +#include #include #include #include @@ -115,6 +116,20 @@ TEST_CASE_METHOD( host_reference, "machine_specific" ){ } + SECTION( "has_multiple_features" ){ + + auto value = compass::runtime::accumulate(compass::feature::avx(),compass::feature::sse4(),compass::feature::sse3()); + + const bool expected = (expected_has_avx || expected_has_sse4 || expected_has_sse3 ); + REQUIRE(bool(value) == expected ); + std::bitset<3> mask((unsigned long)value); + + REQUIRE(mask[0] == expected_has_avx); + REQUIRE(mask[1] == expected_has_sse4); + REQUIRE(mask[2] == expected_has_sse3); + + } + SECTION( "has_avx2_right" ){