diff --git a/.github/scripts/conan-ci-setup.sh b/.github/scripts/conan-ci-setup.sh index 0018fd4..819aad5 100644 --- a/.github/scripts/conan-ci-setup.sh +++ b/.github/scripts/conan-ci-setup.sh @@ -8,7 +8,7 @@ pip3 install conan conan profile detect -f -std=20 +std=23 profile="$(conan profile path default)" mv "$profile" "${profile}.bak" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23e3220..a29695c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,20 +36,18 @@ jobs: if: always() run: cmake -P cmake/spell.cmake - sanitize: + test-avx512: needs: [lint] - runs-on: ubuntu-22.04 + strategy: + matrix: + os: [ubuntu-22.04] - env: { CXX: clang++-18 } + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Install Python - uses: actions/setup-python@v5 - with: { python-version: "3.12" } - - name: Install LLVM 18 run: | wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc @@ -57,35 +55,47 @@ jobs: sudo apt update sudo apt install llvm-18 llvm-18-dev llvm-18-tools clang-18 clang-tidy-18 clang-format-18 clang-tools-18 libclang-18-dev -y + - name: Install static analyzers + if: matrix.os == 'ubuntu-22.04' + run: >- + sudo apt-get install clang-tidy-18 cppcheck -y -q + + sudo update-alternatives --install + /usr/bin/clang-tidy clang-tidy + /usr/bin/clang-tidy-18 140 + - name: Conan cache uses: actions/cache@v4 with: - path: conan_cache_save.tgz - key: conan-sanitize-${{ hashFiles('conan*.[pl][yo]*') }} + path: conan_cache_save-${{ matrix.os}}.tgz + key: conan-${{ matrix.os }}-${{ hashFiles('conan*.[pl][yo]*') }} - name: Install dependencies + shell: bash run: bash < .github/scripts/conan-ci-setup.sh - name: Configure - run: cmake --preset=ci-sanitize + shell: pwsh + run: | + $output = cmake -DENABLE_SIMD=ON "--preset=ci-$("${{ matrix.os }}".split("-")[0])" + Write-Output $output + if ($output -match "AVX-512 is supported") { + Write-Output "AVX512 is enabled" + } else { + throw "AVX512 is not available" + } - name: Build - run: cmake --build build/sanitize -j 2 + run: cmake --build build --config Release -j 4 + + - name: Install + run: cmake --install build --config Release --prefix prefix - name: Test - working-directory: build/sanitize - env: - ASAN_OPTIONS: "strict_string_checks=1:\ - detect_stack_use_after_return=1:\ - check_initialization_order=1:\ - strict_init_order=1:\ - detect_leaks=1:\ - halt_on_error=1" - UBSAN_OPTIONS: "print_stacktrace=1:\ - halt_on_error=1" - run: ctest --output-on-failure --no-tests=error -j 2 - - test: + working-directory: build + run: ctest --output-on-failure --no-tests=error -C Release -j 2 + + test-nosimd: needs: [lint] strategy: @@ -113,6 +123,69 @@ jobs: /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-18 140 + - name: Conan cache + uses: actions/cache@v4 + with: + path: conan_cache_save-${{ matrix.os}}.tgz + key: conan-${{ matrix.os }}-${{ hashFiles('conan*.[pl][yo]*') }} + + - name: Install dependencies + shell: bash + run: bash < .github/scripts/conan-ci-setup.sh + + - name: Configure + shell: pwsh + run: | + $output = cmake -DENABLE_SIMD=OFF "--preset=ci-$("${{ matrix.os }}".split("-")[0])" + Write-Output $output + if ($output -match "SIMD is not supported by the compiler") { + Write-Output "SIMD is disabled" + } else { + throw "SIMD is enabled when it should not be" + } + + - name: Build + run: cmake --build build --config Release -j 4 + + - name: Install + run: cmake --install build --config Release --prefix prefix + + - name: Test + working-directory: build + run: ctest --output-on-failure --no-tests=error -C Release -j 2 + + test-neon: + needs: [lint] + + strategy: + matrix: + os: [macos-14] + + runs-on: ${{ matrix.os }} + + env: + CC: /opt/homebrew/opt/llvm@18/bin/clang + CXX: /opt/homebrew/opt/llvm@18/bin/clang++ + CLANG_DIR: '/opt/homebrew/opt/llvm@18/bin/clang' + LLVM_DIR: '/opt/homebrew/opt/llvm@18' + + steps: + - uses: actions/checkout@v4 + + - name: Install LLVM 18 + run: | + brew install llvm@18 + + - name: Verify Installation + run: | + ${{ env.CC }} --version + ${{ env.CXX }} --version + + - name: Install static analyzers + if: matrix.os == 'macos-14' + run: >- + brew install cppcheck + - name: Install Python uses: actions/setup-python@v5 with: { python-version: "3.12" } @@ -120,7 +193,7 @@ jobs: - name: Conan cache uses: actions/cache@v4 with: - path: conan_cache_save.tgz + path: conan_cache_save-${{ matrix.os}}.tgz key: conan-${{ matrix.os }}-${{ hashFiles('conan*.[pl][yo]*') }} - name: Install dependencies @@ -129,10 +202,17 @@ jobs: - name: Configure shell: pwsh - run: cmake "--preset=ci-$("${{ matrix.os }}".split("-")[0])" + run: | + $output = cmake -DENABLE_SIMD=OFF "--preset=ci-$("${{ matrix.os }}".split("-")[0])" + Write-Output $output + if ($output -match "ARM NEON is supported by the compiler") { + Write-Output "ARM NEON is enabled" + } else { + throw "ARM NEON is not available" + } - name: Build - run: cmake --build build --config Release -j 2 + run: cmake --build build --config Release -j 4 - name: Install run: cmake --install build --config Release --prefix prefix @@ -140,4 +220,3 @@ jobs: - name: Test working-directory: build run: ctest --output-on-failure --no-tests=error -C Release -j 2 - diff --git a/CMakeLists.txt b/CMakeLists.txt index 1578dc5..8444354 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,9 @@ project( include(cmake/project-is-top-level.cmake) include(cmake/variables.cmake) -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +# set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") -# add_compile_options(-fno-inline -fno-omit-frame-pointer) +add_compile_options(-fno-inline -fno-omit-frame-pointer) # ---- Declare library ---- @@ -30,8 +30,15 @@ add_library( source/units/coordinates.cpp ) +option(ENABLE_SIMD "Enable SIMD instructions if available" ON) + include(CheckCXXCompilerFlag) -check_cxx_compiler_flag("-mavx512f -mavx512dq -mavx512vl -mavx512bf16" HAS_AVX512) +check_cxx_source_compiles(" + #include + int main() { + __m512i t = _mm512_set1_epi64(0); + return 0; + }" HAS_AVX512) check_cxx_source_compiles(" #include int main() { @@ -39,15 +46,15 @@ check_cxx_source_compiles(" return 0; }" HAS_NEON) -if (HAS_ALL_AVX512) +if (HAS_AVX512 AND ENABLE_SIMD) message(STATUS "AVX-512 is supported by the compiler.") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512dq -mavx512vl -mavx512bf16") target_sources(fractal-generator_lib PRIVATE source/mandelbrot/equations_simd.cpp) -elseif(HAS_NEON) +elseif(HAS_NEON AND ENABLE_SIMD) message(STATUS "ARM NEON is supported by the compiler.") target_sources(fractal-generator_lib PRIVATE source/mandelbrot/equations_neon.cpp) else() - message(STATUS "SIMD is not fully supported by the compiler. SIMD will not be enabled.") + message(STATUS "SIMD is not supported by the compiler. SIMD will not be enabled.") target_sources(fractal-generator_lib PRIVATE source/mandelbrot/equations_compat.cpp) endif() diff --git a/source/config.hpp b/source/config.hpp index 1ec169f..c528cd5 100644 --- a/source/config.hpp +++ b/source/config.hpp @@ -12,8 +12,8 @@ constexpr std::size_t WINDOW_HEIGHT = 600UZ * 2; constexpr std::size_t FRAME_RATE = 60UZ; constexpr complex_domain START_COMPLEX_DOMAIN{ - complex_coordinate{-2, -1}, - complex_coordinate{1, 1.25 } + complex_coordinate{-2, -1 }, + complex_coordinate{1, 1.25} }; const complex_underlying MANDELBROT_DIVERGENCE_NORM = 4;