Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support compiling with -std=c++* (and -std=gnu++*) #70

Merged
merged 27 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
347 changes: 0 additions & 347 deletions .github/workflows/ci-sage.yml

This file was deleted.

14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: |
cmake . -G "Unix Makefiles" -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${{matrix.config}} -DCMAKE_CXX_FLAGS="-Wall -Wextra -pedantic -Werror"
grep "^OpenMP:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand Down Expand Up @@ -118,7 +118,7 @@ jobs:
run: |
cmake . -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${{matrix.config}} -DCMAKE_CXX_FLAGS="-Wall -Wextra -pedantic -Werror"
grep "^OpenMP:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand Down Expand Up @@ -152,7 +152,7 @@ jobs:
run: |
cmake . -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${{matrix.config}} -DCMAKE_CXX_FLAGS="-mpopcnt -Wall -Wextra -pedantic -Werror"
grep "^OpenMP:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand Down Expand Up @@ -252,7 +252,7 @@ jobs:
run: |
cmake . -DBUILD_TESTS=ON -DBUILD_MANPAGE=ON -DCMAKE_BUILD_TYPE=${{matrix.config}} -DCMAKE_CXX_FLAGS="-Wall -Wextra -pedantic -Werror"
grep "^OpenMP.*:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand Down Expand Up @@ -290,7 +290,7 @@ jobs:
run: |
cmake . -DBUILD_TESTS=ON -DBUILD_MANPAGE=ON -DCMAKE_BUILD_TYPE=${{matrix.config}} -DCMAKE_CXX_FLAGS="-mpopcnt -Wall -Wextra -pedantic -Werror"
grep "^OpenMP.*:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand Down Expand Up @@ -326,7 +326,7 @@ jobs:
run: |
LDFLAGS="-L$(brew --prefix libomp)/lib" cmake . -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${{matrix.config}} -DCMAKE_CXX_FLAGS="-I$(brew --prefix libomp)/include -Wall -Wextra -pedantic -Werror"
grep "^OpenMP.*:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand All @@ -353,7 +353,7 @@ jobs:
run: |
cmake . -DBUILD_TESTS=ON
grep "^OpenMP:INTERNAL=1$" CMakeCache.txt
grep "^int128.*:INTERNAL=1$" CMakeCache.txt
grep "^int128_STL.*:INTERNAL=1$" CMakeCache.txt
cmake --build . --parallel --verbose
- name: CTest (unit tests)
run: ctest -j2
Expand Down
92 changes: 45 additions & 47 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,6 @@ if(NOT STATICALLY_LINK_LIBPRIMECOUNT)
endif()
endif()

# Set default build type to Release ##################################

if(NOT CMAKE_VERSION VERSION_LESS 3.9)
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
elseif(CMAKE_CONFIGURATION_TYPES)
set(isMultiConfig TRUE)
endif()

if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()

# primecount binary source files #####################################

set(BIN_SRC src/app/CmdOptions.cpp
Expand Down Expand Up @@ -154,20 +141,24 @@ set(LIB_SRC src/api.cpp
src/gourdon/SegmentedPiTable.cpp
src/gourdon/Sigma.cpp)

# Required includes ##################################################
# Use libdivide.h (fast integer divison) #############################

include(GNUInstallDirs)
if(WITH_LIBDIVIDE)
set(LIB_SRC ${LIB_SRC} src/deleglise-rivat/S2_easy_libdivide.cpp)
set(LIB_SRC ${LIB_SRC} src/gourdon/AC_libdivide.cpp)
else()
set(LIB_SRC ${LIB_SRC} src/deleglise-rivat/S2_easy.cpp)
set(LIB_SRC ${LIB_SRC} src/gourdon/AC.cpp)
endif()

# Use -Wno-uninitialized with GCC compiler ###########################
# Enable __float128 support (requires libquadmath) ###################

# GCC's -Wuninitialized enabled with -Wall -pedantic causes
# false postive warnings in libprimecount:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107287
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WNO_UNINITIALIZED "-Wno-uninitialized")
if(WITH_FLOAT128)
set(LIB_QUADMATH "quadmath")
set(HAVE_FLOAT128 "HAVE_FLOAT128")
endif()

# libprimecount compile definitions ##################################
# Use 32-bit integer division ########################################

# Check at runtime if the dividend and divisor are < 2^32 and
# if so use 32-bit integer division instead of 64-bit integer
Expand All @@ -177,11 +168,13 @@ if(WITH_DIV32)
set(ENABLE_DIV32 "ENABLE_DIV32")
endif()

# Enable expensive debugging assertions.
# These assertions enable e.g. bounds checks
# for the Vector and Array types.
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(ENABLE_ASSERT "ENABLE_ASSERT")
# Use -Wno-uninitialized with GCC compiler ###########################

# GCC's -Wuninitialized enabled with -Wall -pedantic causes
# false postive warnings in libprimecount:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107287
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WNO_UNINITIALIZED "-Wno-uninitialized")
endif()

# Check if int128_t is supported #####################################
Expand All @@ -192,34 +185,39 @@ include("${PROJECT_SOURCE_DIR}/cmake/int128_t.cmake")

if(WITH_MULTIARCH)
include("${PROJECT_SOURCE_DIR}/cmake/multiarch_avx512_vpopcnt.cmake")
if(multiarch_avx512_vpopcnt)
set(ENABLE_MULTIARCH_AVX512_BMI2 "ENABLE_MULTIARCH_AVX512_BMI2")
endif()
endif()

# Use libdivide.h (fast integer divison) #############################
# Check for OpenMP ###################################################

if(WITH_LIBDIVIDE)
set(LIB_SRC ${LIB_SRC} src/deleglise-rivat/S2_easy_libdivide.cpp)
set(LIB_SRC ${LIB_SRC} src/gourdon/AC_libdivide.cpp)
else()
set(LIB_SRC ${LIB_SRC} src/deleglise-rivat/S2_easy.cpp)
set(LIB_SRC ${LIB_SRC} src/gourdon/AC.cpp)
if(WITH_OPENMP)
include("${PROJECT_SOURCE_DIR}/cmake/OpenMP.cmake")
endif()

# Enable __float128 support (requires libquadmath) ###################
# Set default build type to Release ##################################

if(WITH_FLOAT128)
set(LIB_QUADMATH "quadmath")
set(HAVE_FLOAT128 "HAVE_FLOAT128")
# We do this after the C++ compilation tests above (include *.cmake)
# so that those tests are compiled without optimization flags
# which should speed up the cmake configure step.

if(NOT CMAKE_VERSION VERSION_LESS 3.9)
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
elseif(CMAKE_CONFIGURATION_TYPES)
set(isMultiConfig TRUE)
endif()

# Check for OpenMP ###################################################
if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()

if(WITH_OPENMP)
include("${PROJECT_SOURCE_DIR}/cmake/OpenMP.cmake")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(ENABLE_ASSERT "ENABLE_ASSERT")
endif()

# Required includes ##################################################

include(GNUInstallDirs)

# libprimesieve ######################################################

# By default the libprimesieve dependency is built from source
Expand Down Expand Up @@ -259,7 +257,7 @@ if(BUILD_SHARED_LIBS)
set_target_properties(libprimecount PROPERTIES SOVERSION ${PRIMECOUNT_VERSION_MAJOR})
set_target_properties(libprimecount PROPERTIES VERSION ${PRIMECOUNT_VERSION})
target_compile_options(libprimecount PRIVATE "${WNO_UNINITIALIZED}")
target_compile_definitions(libprimecount PRIVATE "${HAVE_FLOAT128}" "${DISABLE_INT128}" "${ENABLE_DIV32}" "${ENABLE_ASSERT}" "${ENABLE_MULTIARCH_AVX512_BMI2}")
target_compile_definitions(libprimecount PRIVATE "${HAVE_FLOAT128}" "${DISABLE_INT128}" "${ENABLE_DIV32}" "${ENABLE_ASSERT}" "${ENABLE_MULTIARCH_AVX512_BMI2}" "${ENABLE_INT128_STL_PATCH}" "${ENABLE_INT128_OPENMP_PATCH}")
target_link_libraries(libprimecount PRIVATE primesieve::primesieve "${LIB_OPENMP}" "${LIB_QUADMATH}" "${LIB_ATOMIC}")

target_compile_features(libprimecount
Expand All @@ -284,7 +282,7 @@ if(BUILD_STATIC_LIBS)
add_library(libprimecount-static STATIC ${LIB_SRC})
set_target_properties(libprimecount-static PROPERTIES OUTPUT_NAME primecount)
target_compile_options(libprimecount-static PRIVATE "${WNO_UNINITIALIZED}")
target_compile_definitions(libprimecount-static PRIVATE "${HAVE_FLOAT128}" "${DISABLE_INT128}" "${ENABLE_DIV32}" "${ENABLE_ASSERT}" "${ENABLE_MULTIARCH_AVX512_BMI2}")
target_compile_definitions(libprimecount-static PRIVATE "${HAVE_FLOAT128}" "${DISABLE_INT128}" "${ENABLE_DIV32}" "${ENABLE_ASSERT}" "${ENABLE_MULTIARCH_AVX512_BMI2}" "${ENABLE_INT128_STL_PATCH}" "${ENABLE_INT128_OPENMP_PATCH}")
target_link_libraries(libprimecount-static PRIVATE primesieve::primesieve "${LIB_OPENMP}" "${LIB_QUADMATH}" "${LIB_ATOMIC}")

if(WITH_MSVC_CRT_STATIC)
Expand Down Expand Up @@ -320,7 +318,7 @@ endif()
if(BUILD_PRIMECOUNT)
add_executable(primecount ${BIN_SRC})
target_link_libraries(primecount PRIVATE primecount::primecount primesieve::primesieve)
target_compile_definitions(primecount PRIVATE "${DISABLE_INT128}" "${ENABLE_DIV32}" "${ENABLE_ASSERT}")
target_compile_definitions(primecount PRIVATE "${DISABLE_INT128}" "${ENABLE_DIV32}" "${ENABLE_ASSERT}" "${ENABLE_INT128_STL_PATCH}" "${ENABLE_INT128_OPENMP_PATCH}")
target_compile_features(primecount PRIVATE cxx_auto_type)
install(TARGETS primecount DESTINATION ${CMAKE_INSTALL_BINDIR})

Expand Down
7 changes: 6 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
Changes in primecount-7.13, 2024-04-04
Changes in primecount-7.13, 2024-04-08

* Delete ci-sage.yml, it has not been updated in 3 years and I
don't want to maintain it. I feel like this CI script should
be part of SageMath, not primecount.
* Added AVX512 runtime dispatching for x86 CPUs.
* CMakeLists.txt: New WITH_MULTIARCH option (default ON).
* Sieve_count.cpp: New AVX512 popcount algorithm for x86 CPUs.
* Sieve_count.cpp: New ARM SVE popcount algorithm.
* int128.cmake: Improve int128_t support for Windows.
* OpenMP.cmake: Improve LLVM/Clang OpenMP detection.

Changes in primecount-7.12, 2024-04-01

Expand Down
47 changes: 40 additions & 7 deletions cmake/OpenMP.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Check if OpenMP supports 128-bit integers out of the box
# or if we have to link against libatomic.

include(CheckCXXSourceCompiles)
include(CMakePushCheckState)

Expand All @@ -8,8 +11,8 @@ if(NOT (OpenMP_FOUND OR OpenMP_CXX_FOUND))
message(STATUS "Performing Test OpenMP - Failed")
endif()

# Check if libatomic is required (usually by Clang)
# to support 128-bit integers with OpenMP.
# CMake has found OpenMP, now we need to check
# if OpenMP supports 128-bit integers.
if(OpenMP_FOUND OR OpenMP_CXX_FOUND)
cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES "${PROJECT_SOURCE_DIR}/include")
Expand All @@ -24,7 +27,7 @@ if(OpenMP_FOUND OR OpenMP_CXX_FOUND)
set(CMAKE_REQUIRED_DEFINITIONS "-D${DISABLE_INT128}")
endif()

# Check if compiles without libatomic
# Check if OpenMP supports 128-bit integers
check_cxx_source_compiles("
#include <int128_t.hpp>
#include <omp.h>
Expand All @@ -42,8 +45,9 @@ if(OpenMP_FOUND OR OpenMP_CXX_FOUND)
return 0;
}" OpenMP)

# Our code requires libatomic to compile
if(NOT OpenMP)
# Try if OpenMP works if we link against libatomic.
# This is sometimes required for LLVM/Clang.
find_library(LIB_ATOMIC NAMES atomic atomic.so.1 libatomic.so.1)

if(NOT LIB_ATOMIC)
Expand All @@ -58,7 +62,7 @@ if(OpenMP_FOUND OR OpenMP_CXX_FOUND)

set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "${LIB_ATOMIC}")

# Check if compiles with libatomic
# Check if OpenMP compiles with libatomic
check_cxx_source_compiles("
#include <int128_t.hpp>
#include <omp.h>
Expand All @@ -78,13 +82,42 @@ if(OpenMP_FOUND OR OpenMP_CXX_FOUND)

if(NOT OpenMP_with_libatomic)
set(LIB_ATOMIC "")

if (NOT DISABLE_INT128)
# As a last resort check if OpenMP supports int128_t if
# we include our <int128_OpenMP_patch.hpp> header.
# In this case OpenMP will use critical sections instead
# of atomics for 128-bit integers which is slightly less
# efficient. (required for LLVM/Clang on Windows)
check_cxx_source_compiles("
#include <int128_t.hpp>
#include <int128_OpenMP_patch.hpp>
#include <omp.h>
#include <stdint.h>
#include <iostream>
int main(int, char** argv) {
using primecount::maxint_t;
uintptr_t n = (uintptr_t) argv;
maxint_t sum = (maxint_t) n;
int iters = (int) n;
#pragma omp parallel for reduction(+: sum)
for (int i = 0; i < iters; i++)
sum += (i / 3) * omp_get_thread_num();
std::cout << (long) sum;
return 0;
}" OpenMP_int128_patch)

if(OpenMP_int128_patch)
set(ENABLE_INT128_OPENMP_PATCH "ENABLE_INT128_OPENMP_PATCH")
endif()
endif()
endif()
endif()

cmake_pop_check_state()

# OpenMP has been tested successfully, enable it
if(OpenMP OR OpenMP_with_libatomic)
if(OpenMP OR OpenMP_with_libatomic OR OpenMP_int128_patch)
if(TARGET OpenMP::OpenMP_CXX)
set(LIB_OPENMP "OpenMP::OpenMP_CXX")
else()
Expand All @@ -99,7 +132,7 @@ if(OpenMP_FOUND OR OpenMP_CXX_FOUND)
endif()

# OpenMP test has failed, print warning message
if(NOT OpenMP AND NOT OpenMP_with_libatomic)
if(NOT OpenMP AND NOT OpenMP_with_libatomic AND NOT OpenMP_int128_patch)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|LLVM")
message(WARNING "Install the OpenMP library (libomp) to enable multithreading in primecount!")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
Expand Down
Loading
Loading