From 5ed95e67c369999718ff71442b64b275142cc967 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 19:31:30 -0700 Subject: [PATCH 01/17] Adding Catch tests --- .gitignore | 4 ++ CMakeLists.txt | 12 ++-- test/CMakeLists.txt | 11 ++++ test/CPM.cmake | 24 ++++++++ test/test.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 test/CMakeLists.txt create mode 100644 test/CPM.cmake create mode 100644 test/test.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ba8b72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build*/ + +.vscode/ +.idea/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 704cc90..bc0085f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("/arch:AVX2" COMPILER_OPT_ARCH_AVX_MSVC_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-mavx -mfma" COMPILER_OPT_ARCH_AVX_GCC_CLANG_SUPPORTED) if(COMPILER_OPT_ARCH_AVX_MSVC_SUPPORTED) - message(STATUS "Compiler supports flags: /arch:AVX2") + message(STATUS "chowdsp_fft -- Compiler supports flags: /arch:AVX2") add_library(chowdsp_fft_avx STATIC simd/chowdsp_fft_impl_avx.cpp) target_compile_options(chowdsp_fft_avx PRIVATE /arch:AVX2) target_compile_definitions(chowdsp_fft_avx PRIVATE _USE_MATH_DEFINES=1) @@ -25,21 +25,25 @@ if(COMPILER_OPT_ARCH_AVX_MSVC_SUPPORTED) target_compile_definitions(chowdsp_fft PRIVATE CHOWDSP_FFT_COMPILER_SUPPORTS_AVX=1) else() if(COMPILER_OPT_ARCH_AVX_GCC_CLANG_SUPPORTED) - message(STATUS "Compiler supports flags: -mavx2 -mfma") + message(STATUS "chowdsp_fft -- Compiler supports flags: -mavx2 -mfma") add_library(chowdsp_fft_avx STATIC simd/chowdsp_fft_impl_avx.cpp) target_compile_options(chowdsp_fft_avx PRIVATE -mavx2 -mfma -Wno-unused-command-line-argument) target_compile_definitions(chowdsp_fft_avx PRIVATE _USE_MATH_DEFINES=1) target_link_libraries(chowdsp_fft PRIVATE chowdsp_fft_avx) target_compile_definitions(chowdsp_fft PRIVATE CHOWDSP_FFT_COMPILER_SUPPORTS_AVX=1) else() - message(STATUS "Compiler DOES NOT supports flags: -mavx2 -mfma") + message(STATUS "chowdsp_fft -- Compiler DOES NOT supports flags: -mavx2 -mfma") target_compile_definitions(chowdsp_fft PRIVATE CHOWDSP_FFT_COMPILER_SUPPORTS_AVX=0) endif() endif() ## JUCE compatibility if(EXISTS "${JUCE_MODULES_DIR}") - message(STATUS "Configuring chowdsp_fft for JUCE") + message(STATUS "chowdsp_fft -- Configuring chowdsp_fft_juce") juce_add_module(chowdsp_fft_juce ALIAS_NAMESPACE chowdsp) target_link_libraries(chowdsp_fft_juce INTERFACE chowdsp_fft) endif() + +if(CHOWDSP_FFT_TESTING) + add_subdirectory(test) +endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..6cb3ef4 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,11 @@ +message(STATUS "chowdsp_fft -- Configuring tests") + +include(CPM.cmake) +CPMAddPackage("gh:catchorg/Catch2@3.2.1") +include(${Catch2_SOURCE_DIR}/extras/Catch.cmake) +CPMAddPackage("bb:jpommier/pffft#master") + +add_executable(test_chowsdp_fft_cpp test.cpp ${pffft_SOURCE_DIR}/pffft.c) +target_link_libraries(test_chowsdp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2WithMain) +target_include_directories(test_chowsdp_fft_cpp PRIVATE ${pffft_SOURCE_DIR}) +target_compile_definitions(test_chowsdp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) diff --git a/test/CPM.cmake b/test/CPM.cmake new file mode 100644 index 0000000..a139e51 --- /dev/null +++ b/test/CPM.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.40.2) +set(CPM_HASH_SUM "c8cdc32c03816538ce22781ed72964dc864b2a34a310d3b7104812a5ca2d835d") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 0000000..31b5dc8 --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,133 @@ +#include +#include + +#include +#include + +void compare (const float* ref, const float* test, int N) +{ + const auto tol = 1.0e-6f * (float) N / 8.0f; + for (size_t n = 0; n < N; ++n) + REQUIRE (test[n] == Catch::Approx { ref[n] }.margin(tol)); +} + +void test_complex (int N, bool use_avx = false) +{ + auto* data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N * 2); + auto* data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N * 2); + auto* work_data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N * 2); + auto* work_data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N * 2); + + for (int i = 0; i < N; ++i) + { + data[i * 2] = std::sin (3.14f * (100.0f / 48000.0f) * (float) i); + data[i * 2 + 1] = std::cos (3.14f * (100.0f / 48000.0f) * (float) i); + } + std::copy (data, data + N * 2, data_ref); + + auto* fft_setup = chowdsp::fft::fft_new_setup (N, chowdsp::fft::FFT_COMPLEX, use_avx); + assert (fft_setup != nullptr); + auto* pffft_setup = pffft_new_setup (N, PFFFT_COMPLEX); + + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_FORWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_FORWARD); + + compare (data_ref, data, N * 2); + + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_BACKWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); + + const auto norm_gain = 1.0f / static_cast (N); + for (size_t n = 0; n < N * 2; ++n) + { + data[n] *= norm_gain; + data_ref[n] *= norm_gain; + } + + compare (data_ref, data, N * 2); + + chowdsp::fft::fft_destroy_setup (fft_setup); + pffft_destroy_setup (pffft_setup); + chowdsp::fft::aligned_free (data); + pffft_aligned_free (data_ref); + chowdsp::fft::aligned_free (work_data); + pffft_aligned_free (work_data_ref); +} + +void test_real (int N, bool use_avx = false) +{ + auto* data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N); + auto* data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N); + auto* work_data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N); + auto* work_data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N); + + for (int i = 0; i < N; ++i) + { + data[i] = std::sin (3.14f * (100.0f / 48000.0f) * (float) i); + } + std::copy (data, data + N, data_ref); + + auto* fft_setup = chowdsp::fft::fft_new_setup (N, chowdsp::fft::FFT_REAL, use_avx); + assert (fft_setup != nullptr); + auto* pffft_setup = pffft_new_setup (N, PFFFT_REAL); + + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_FORWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_FORWARD); + + compare (data_ref, data, N); + + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_BACKWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); + + const auto norm_gain = 1.0f / static_cast (N); + for (int n = 0; n < N; ++n) + { + data[n] *= norm_gain; + data_ref[n] *= norm_gain; + } + + compare (data_ref, data, N); + + chowdsp::fft::fft_destroy_setup (fft_setup); + pffft_destroy_setup (pffft_setup); + chowdsp::fft::aligned_free (data); + pffft_aligned_free (data_ref); + chowdsp::fft::aligned_free (work_data); + pffft_aligned_free (work_data_ref); +} + +TEST_CASE("FFT SSE/NEON") +{ + for (size_t i = 5; i < 20; ++i) + { + const auto fft_size = 1 << i; + SECTION ("Testing Complex FFT with size: " + std::to_string (fft_size)) + { + test_complex (fft_size); + } + + SECTION ("Testing Real FFT with size: " + std::to_string (fft_size)) + { + test_real (fft_size); + } + } +} + +#if defined(__SSE2__) +TEST_CASE("FFT AVX") +{ + for (size_t i = 5; i < 20; ++i) + { + const auto fft_size = 1 << i; + SECTION ("Testing Complex FFT with size: " + std::to_string (fft_size)) + { + test_complex (fft_size, true); + } + + SECTION ("Testing Real FFT with size: " + std::to_string (fft_size)) + { + test_real (fft_size, true); + } + } +} +#endif From 1e33ce4baa5815a86a13e47a3bb75e09f6f19b9f Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 19:46:08 -0700 Subject: [PATCH 02/17] Adding C test --- chowdsp_fft.h | 1 + test/CMakeLists.txt | 5 ++ test/test.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ test/test.cpp | 8 +-- 4 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 test/test.c diff --git a/chowdsp_fft.h b/chowdsp_fft.h index efd6e34..92597db 100644 --- a/chowdsp_fft.h +++ b/chowdsp_fft.h @@ -57,6 +57,7 @@ namespace chowdsp::fft { #else #include +#include #endif /* direction of the transform */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6cb3ef4..f91c8cc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,3 +9,8 @@ add_executable(test_chowsdp_fft_cpp test.cpp ${pffft_SOURCE_DIR}/pffft.c) target_link_libraries(test_chowsdp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2WithMain) target_include_directories(test_chowsdp_fft_cpp PRIVATE ${pffft_SOURCE_DIR}) target_compile_definitions(test_chowsdp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) + +add_executable(test_chowsdp_fft_c test.c ${pffft_SOURCE_DIR}/pffft.c) +target_link_libraries(test_chowsdp_fft_c PRIVATE chowdsp_fft) +target_include_directories(test_chowsdp_fft_c PRIVATE ${pffft_SOURCE_DIR}) +target_compile_definitions(test_chowsdp_fft_c PRIVATE _USE_MATH_DEFINES=1) diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..1980687 --- /dev/null +++ b/test/test.c @@ -0,0 +1,128 @@ +#include +#include + +#include +#include +#include +#include +#include + +void compare (const float* ref, const float* test, int N) +{ + const float tol = 1.0e-6f * (float) N / 8.0f; + for (int n = 0; n < N; ++n) + assert (fabsf (ref[n] - test[n]) < tol); +} + +void test_complex (int N, bool use_avx) +{ + float* data = (float*) aligned_malloc (sizeof (float) * N * 2); + float* data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N * 2); + float* work_data = (float*) aligned_malloc (sizeof (float) * N * 2); + float* work_data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N * 2); + + for (int i = 0; i < N; ++i) + { + data[i * 2] = sinf (3.14f * (100.0f / 48000.0f) * (float) i); + data[i * 2 + 1] = cosf (3.14f * (100.0f / 48000.0f) * (float) i); + } + memcpy (data_ref, data, N * 2 * sizeof (float)); + + void* fft_setup = fft_new_setup (N, FFT_COMPLEX, use_avx); + assert (fft_setup != NULL); + PFFFT_Setup* pffft_setup = pffft_new_setup (N, PFFFT_COMPLEX); + + fft_transform (fft_setup, data, data, work_data, FFT_FORWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_FORWARD); + + compare (data_ref, data, N * 2); + + fft_transform (fft_setup, data, data, work_data, FFT_BACKWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); + + const float norm_gain = 1.0f / (float) N; + for (int n = 0; n < N * 2; ++n) + { + data[n] *= norm_gain; + data_ref[n] *= norm_gain; + } + + compare (data_ref, data, N * 2); + + fft_destroy_setup (fft_setup); + pffft_destroy_setup (pffft_setup); + aligned_free (data); + pffft_aligned_free (data_ref); + aligned_free (work_data); + pffft_aligned_free (work_data_ref); +} + +void test_real (int N, bool use_avx) +{ + float* data = (float*) aligned_malloc (sizeof (float) * N); + float* data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N); + float* work_data = (float*) aligned_malloc (sizeof (float) * N); + float* work_data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N); + + for (int i = 0; i < N; ++i) + { + data[i] = sinf (3.14f * (100.0f / 48000.0f) * (float) i); + } + memcpy (data_ref, data, N * sizeof (float)); + + void* fft_setup = fft_new_setup (N, FFT_REAL, use_avx); + assert (fft_setup != NULL); + PFFFT_Setup* pffft_setup = pffft_new_setup (N, PFFFT_REAL); + + fft_transform (fft_setup, data, data, work_data, FFT_FORWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_FORWARD); + + compare (data_ref, data, N); + + fft_transform (fft_setup, data, data, work_data, FFT_BACKWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); + + const float norm_gain = 1.0f / (float) N; + for (int n = 0; n < N; ++n) + { + data[n] *= norm_gain; + data_ref[n] *= norm_gain; + } + + compare (data_ref, data, N); + + fft_destroy_setup (fft_setup); + pffft_destroy_setup (pffft_setup); + aligned_free (data); + pffft_aligned_free (data_ref); + aligned_free (work_data); + pffft_aligned_free (work_data_ref); +} + + +int main() +{ + printf ("Running SSE/NEON Tests\n"); + for (int i = 5; i < 20; ++i) + { + const int fft_size = 1 << i; + printf ("Testing Complex FFT with size: %d\n", fft_size); + test_complex (fft_size, false); + printf ("Testing Real FFT with size: %d\n", fft_size); + test_real (fft_size, false); + } + +#if defined(__SSE2__) + printf ("Running AVX Tests\n"); + for (int i = 5; i < 20; ++i) + { + const int fft_size = 1 << i; + printf ("Testing Complex FFT with size: %d\n", fft_size); + test_complex (fft_size, true); + printf ("Testing Real FFT with size: %d\n", fft_size); + test_real (fft_size, true); + } +#endif + + return 0; +} diff --git a/test/test.cpp b/test/test.cpp index 31b5dc8..784bdac 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -7,7 +7,7 @@ void compare (const float* ref, const float* test, int N) { const auto tol = 1.0e-6f * (float) N / 8.0f; - for (size_t n = 0; n < N; ++n) + for (int n = 0; n < N; ++n) REQUIRE (test[n] == Catch::Approx { ref[n] }.margin(tol)); } @@ -38,7 +38,7 @@ void test_complex (int N, bool use_avx = false) pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); const auto norm_gain = 1.0f / static_cast (N); - for (size_t n = 0; n < N * 2; ++n) + for (int n = 0; n < N * 2; ++n) { data[n] *= norm_gain; data_ref[n] *= norm_gain; @@ -98,7 +98,7 @@ void test_real (int N, bool use_avx = false) TEST_CASE("FFT SSE/NEON") { - for (size_t i = 5; i < 20; ++i) + for (int i = 5; i < 20; ++i) { const auto fft_size = 1 << i; SECTION ("Testing Complex FFT with size: " + std::to_string (fft_size)) @@ -116,7 +116,7 @@ TEST_CASE("FFT SSE/NEON") #if defined(__SSE2__) TEST_CASE("FFT AVX") { - for (size_t i = 5; i < 20; ++i) + for (int i = 5; i < 20; ++i) { const auto fft_size = 1 << i; SECTION ("Testing Complex FFT with size: " + std::to_string (fft_size)) From b5e21321dda36715ba8ea2f8368c902c8d5b08aa Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 19:55:25 -0700 Subject: [PATCH 03/17] Setting up benchmark tool --- CMakeLists.txt | 1 + bench/CMakeLists.txt | 6 +++ bench/bench.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 bench/CMakeLists.txt create mode 100644 bench/bench.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bc0085f..540ffd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,4 +46,5 @@ endif() if(CHOWDSP_FFT_TESTING) add_subdirectory(test) + add_subdirectory(bench) endif() diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt new file mode 100644 index 0000000..db2399a --- /dev/null +++ b/bench/CMakeLists.txt @@ -0,0 +1,6 @@ +message(STATUS "chowdsp_fft -- Configuring benchmarks ${CMAKE_BINARY_DIR}/_deps/pffft-src") + +add_executable(bench_chowsdp_fft bench.cpp) +target_link_libraries(bench_chowsdp_fft PRIVATE chowdsp_fft) +target_include_directories(bench_chowsdp_fft PRIVATE ${CMAKE_BINARY_DIR}/_deps/pffft-src) +target_compile_definitions(bench_chowsdp_fft PRIVATE _USE_MATH_DEFINES=1) diff --git a/bench/bench.cpp b/bench/bench.cpp new file mode 100644 index 0000000..d4bbfac --- /dev/null +++ b/bench/bench.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include + +#include +#include +#include + +std::pair bench_complex (int N) +{ + static constexpr int M = 50; + + auto* data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N * 2); + auto* data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N * 2); + auto* work_data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N * 2); + auto* work_data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N * 2); + + for (int i = 0; i < N; ++i) + { + data[i * 2] = std::sin (3.14f * (100.0f / 48000.0f) * (float) i); + data[i * 2 + 1] = std::cos (3.14f * (100.0f / 48000.0f) * (float) i); + } + std::copy (data, data + N * 2, data_ref); + + auto* fft_setup = chowdsp::fft::fft_new_setup (N, chowdsp::fft::FFT_COMPLEX); + assert (fft_setup != nullptr); + auto* pffft_setup = pffft_new_setup (N, PFFFT_COMPLEX); + + auto start = std::chrono::high_resolution_clock::now(); + for (int m = 0; m < M; ++m) + { + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_FORWARD); + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_BACKWARD); + } + auto duration = std::chrono::high_resolution_clock::now() - start; + auto test_duration_seconds = std::chrono::duration (duration).count(); + std::cout << " chowdsp_fft: " << test_duration_seconds << " seconds" << std::endl; + + start = std::chrono::high_resolution_clock::now(); + for (int m = 0; m < M; ++m) + { + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_FORWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); + } + duration = std::chrono::high_resolution_clock::now() - start; + auto ref_duration_seconds = std::chrono::duration (duration).count(); + std::cout << " pffft: " << ref_duration_seconds << " seconds" << std::endl; + + chowdsp::fft::fft_destroy_setup (fft_setup); + pffft_destroy_setup (pffft_setup); + chowdsp::fft::aligned_free (data); + pffft_aligned_free (data_ref); + chowdsp::fft::aligned_free (work_data); + pffft_aligned_free (work_data_ref); + + return { test_duration_seconds, ref_duration_seconds }; +} + +std::pair bench_real (int N) +{ + static constexpr int M = 50; + + auto* data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N); + auto* data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N); + auto* work_data = (float*) chowdsp::fft::aligned_malloc (sizeof (float) * N); + auto* work_data_ref = (float*) pffft_aligned_malloc (sizeof (float) * N); + + for (int i = 0; i < N; ++i) + { + data[i] = std::sin (3.14f * (100.0f / 48000.0f) * (float) i); + } + std::copy (data, data + N, data_ref); + + auto* fft_setup = chowdsp::fft::fft_new_setup (N, chowdsp::fft::FFT_REAL); + assert (fft_setup != nullptr); + auto* pffft_setup = pffft_new_setup (N, PFFFT_REAL); + + auto start = std::chrono::high_resolution_clock::now(); + for (int m = 0; m < M; ++m) + { + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_FORWARD); + chowdsp::fft::fft_transform (fft_setup, data, data, work_data, chowdsp::fft::FFT_BACKWARD); + } + auto duration = std::chrono::high_resolution_clock::now() - start; + auto test_duration_seconds = std::chrono::duration (duration).count(); + std::cout << " chowdsp_fft: " << test_duration_seconds << " seconds" << std::endl; + + start = std::chrono::high_resolution_clock::now(); + for (int m = 0; m < M; ++m) + { + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_FORWARD); + pffft_transform_ordered (pffft_setup, data_ref, data_ref, work_data_ref, PFFFT_BACKWARD); + } + duration = std::chrono::high_resolution_clock::now() - start; + auto ref_duration_seconds = std::chrono::duration (duration).count(); + std::cout << " pffft: " << ref_duration_seconds << " seconds" << std::endl; + + chowdsp::fft::fft_destroy_setup (fft_setup); + pffft_destroy_setup (pffft_setup); + chowdsp::fft::aligned_free (data); + pffft_aligned_free (data_ref); + chowdsp::fft::aligned_free (work_data); + pffft_aligned_free (work_data_ref); + + return { test_duration_seconds, ref_duration_seconds }; +} + +int main() +{ + std::vector durations_cplx_test (15, 0.0f); + std::vector durations_cplx_ref (15, 0.0f); + std::vector durations_real_test (15, 0.0f); + std::vector durations_real_ref (15, 0.0f); + for (size_t i = 5; i < 20; ++i) + { + const auto fft_size = 1 << i; + std::cout << "Benchmarking Complex FFT with size: " << fft_size << std::endl; + std::tie (durations_cplx_test[i-5], durations_cplx_ref[i-5]) = bench_complex (1 << i); + std::cout << "Benchmarking Real FFT with size: " << fft_size << std::endl; + std::tie (durations_real_test[i-5], durations_real_ref[i-5]) = bench_real (1 << i); + } + + return 0; +} From a3b2626a9ca4dbba18d11c87351194173b005f15 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 20:12:45 -0700 Subject: [PATCH 04/17] Set up GitHub Actions --- .github/workflows/bench.yml | 80 ++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 92 +++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 2 +- 3 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/bench.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 0000000..feec8ac --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,80 @@ +name: Bench + +on: + pull_request: + branches: + - main + - develop + push: + branches: + - ci + + workflow_dispatch: + +jobs: + build_and_test: + name: Build/Test plugin on ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false # show all errors for each platform (vs. cancel jobs on error) + matrix: + include: + - name: Linux + os: ubuntu-22.04 + cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15" + nparallel: 4 + - name: Windows + os: windows-2022 + cmake_args: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl + nparallel: 4 + - name: MacOS + os: macos-14 + cmake_args: "" + nparallel: 4 + + steps: + - name: Install Linux Deps + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt install libasound2-dev libcurl4-openssl-dev libx11-dev libxinerama-dev libxext-dev libfreetype6-dev libwebkit2gtk-4.0-dev libglu1-mesa-dev libjack-jackd2-dev + sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" + sudo apt install clang-15 -y + + - name: Install Ninja + if: runner.os == 'Linux' || runner.os == 'Windows' + uses: seanmiddleditch/gha-setup-ninja@master + + - name: Get latest CMake + if: runner.os == 'Linux' || runner.os == 'Windows' + uses: lukka/get-cmake@latest + + - uses: rui314/setup-mold@v1 + if: runner.os == 'Linux' + + - name: Upgrade LLVM + if: runner.os == 'Windows' + run: choco upgrade llvm --version=18.1.8 --allow-downgrade + + - name: Add msbuild to PATH + if: runner.os == 'Windows' + uses: microsoft/setup-msbuild@v2 + + - name: Setup MSVC devcmd + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + token: ${{ secrets.OUR_GITHUB_PAT }} + + - name: Cmake Configure + run: cmake -Bbuild -G"Ninja Multi-Config" -DCHOWDSP_FFT_TESTING=ON ${{ matrix.cmake_args }} + + - name: Build Benchmarks + run: cmake --build build --config Release --parallel ${{ matrix.nparallel }} --target bench_chowdsp_fft + + - name: Run Benchmarks + run: ./build/bench/Release/bench_chowdsp_fft diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..1190f57 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,92 @@ +name: Test + +on: + pull_request: + branches: + - main + - develop + push: + branches: + - ci + + workflow_dispatch: + +jobs: + build_and_test: + name: Build/Test plugin on ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false # show all errors for each platform (vs. cancel jobs on error) + matrix: + include: + - name: Linux + os: ubuntu-22.04 + cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15" + nparallel: 4 + - name: Windows + os: windows-2022 + cmake_args: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl + nparallel: 4 + - name: MacOS + os: macos-14 + cmake_args: "-D\"CMAKE_OSX_ARCHITECTURES=arm64;x86_64\"" + nparallel: 4 + + steps: + - name: Install Linux Deps + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt install libasound2-dev libcurl4-openssl-dev libx11-dev libxinerama-dev libxext-dev libfreetype6-dev libwebkit2gtk-4.0-dev libglu1-mesa-dev libjack-jackd2-dev + sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" + sudo apt install clang-15 -y + + - name: Install Ninja + if: runner.os == 'Linux' || runner.os == 'Windows' + uses: seanmiddleditch/gha-setup-ninja@master + + - name: Get latest CMake + if: runner.os == 'Linux' || runner.os == 'Windows' + uses: lukka/get-cmake@latest + + - uses: rui314/setup-mold@v1 + if: runner.os == 'Linux' + + - name: Upgrade LLVM + if: runner.os == 'Windows' + run: choco upgrade llvm --version=18.1.8 --allow-downgrade + + - name: Add msbuild to PATH + if: runner.os == 'Windows' + uses: microsoft/setup-msbuild@v2 + + - name: Setup MSVC devcmd + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + token: ${{ secrets.OUR_GITHUB_PAT }} + + - name: Cmake Configure + run: cmake -Bbuild -G"Ninja Multi-Config" -DCHOWDSP_FFT_TESTING=ON ${{ matrix.cmake_args }} + + - name: Build Test C++ (Debug) + run: cmake --build build --config Debug --parallel ${{ matrix.nparallel }} --target test_chowdsp_fft_cpp + + - name: Run Test C++ (Debug) + run: ./build/test/Debug/test_chowdsp_fft_cpp + + - name: Build Test C (Debug) + run: cmake --build build --config Debug --parallel ${{ matrix.nparallel }} --target test_chowdsp_fft_c + + - name: Run Test C (Debug) + run: ./build/test/Debug/test_chowdsp_fft_c + + - name: Build Test C++ (Release) + run: cmake --build build --config Release --parallel ${{ matrix.nparallel }} --target test_chowdsp_fft_cpp + + - name: Run Test C++ (Release) + run: ./build/test/Release/test_chowdsp_fft_cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f91c8cc..45755ab 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,7 +3,7 @@ message(STATUS "chowdsp_fft -- Configuring tests") include(CPM.cmake) CPMAddPackage("gh:catchorg/Catch2@3.2.1") include(${Catch2_SOURCE_DIR}/extras/Catch.cmake) -CPMAddPackage("bb:jpommier/pffft#master") +CPMAddPackage("bb:jpommier/pffft#fbc4058602803f40dc554b8a5d2bcc694c005f2f") add_executable(test_chowsdp_fft_cpp test.cpp ${pffft_SOURCE_DIR}/pffft.c) target_link_libraries(test_chowsdp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2WithMain) From a155cccf7048f6b937c3a375310c770d41c75d2a Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 20:15:37 -0700 Subject: [PATCH 05/17] Attempting to fix CI --- .github/workflows/bench.yml | 4 +--- .github/workflows/test.yml | 4 +--- bench/CMakeLists.txt | 8 ++++---- test/CMakeLists.txt | 16 ++++++++-------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index feec8ac..aee06c8 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -13,7 +13,7 @@ on: jobs: build_and_test: - name: Build/Test plugin on ${{ matrix.name }} + name: Benchmark library on ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false # show all errors for each platform (vs. cancel jobs on error) @@ -42,11 +42,9 @@ jobs: sudo apt install clang-15 -y - name: Install Ninja - if: runner.os == 'Linux' || runner.os == 'Windows' uses: seanmiddleditch/gha-setup-ninja@master - name: Get latest CMake - if: runner.os == 'Linux' || runner.os == 'Windows' uses: lukka/get-cmake@latest - uses: rui314/setup-mold@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1190f57..9dc4e1f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ on: jobs: build_and_test: - name: Build/Test plugin on ${{ matrix.name }} + name: Test library on ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: fail-fast: false # show all errors for each platform (vs. cancel jobs on error) @@ -42,11 +42,9 @@ jobs: sudo apt install clang-15 -y - name: Install Ninja - if: runner.os == 'Linux' || runner.os == 'Windows' uses: seanmiddleditch/gha-setup-ninja@master - name: Get latest CMake - if: runner.os == 'Linux' || runner.os == 'Windows' uses: lukka/get-cmake@latest - uses: rui314/setup-mold@v1 diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index db2399a..a27959e 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -1,6 +1,6 @@ message(STATUS "chowdsp_fft -- Configuring benchmarks ${CMAKE_BINARY_DIR}/_deps/pffft-src") -add_executable(bench_chowsdp_fft bench.cpp) -target_link_libraries(bench_chowsdp_fft PRIVATE chowdsp_fft) -target_include_directories(bench_chowsdp_fft PRIVATE ${CMAKE_BINARY_DIR}/_deps/pffft-src) -target_compile_definitions(bench_chowsdp_fft PRIVATE _USE_MATH_DEFINES=1) +add_executable(bench_chowdsp_fft bench.cpp) +target_link_libraries(bench_chowdsp_fft PRIVATE chowdsp_fft) +target_include_directories(bench_chowdsp_fft PRIVATE ${CMAKE_BINARY_DIR}/_deps/pffft-src) +target_compile_definitions(bench_chowdsp_fft PRIVATE _USE_MATH_DEFINES=1) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 45755ab..34caf5e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,12 +5,12 @@ CPMAddPackage("gh:catchorg/Catch2@3.2.1") include(${Catch2_SOURCE_DIR}/extras/Catch.cmake) CPMAddPackage("bb:jpommier/pffft#fbc4058602803f40dc554b8a5d2bcc694c005f2f") -add_executable(test_chowsdp_fft_cpp test.cpp ${pffft_SOURCE_DIR}/pffft.c) -target_link_libraries(test_chowsdp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2WithMain) -target_include_directories(test_chowsdp_fft_cpp PRIVATE ${pffft_SOURCE_DIR}) -target_compile_definitions(test_chowsdp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) +add_executable(test_chowdsp_fft_cpp test.cpp ${pffft_SOURCE_DIR}/pffft.c) +target_link_libraries(test_chowdsp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2WithMain) +target_include_directories(test_chowdsp_fft_cpp PRIVATE ${pffft_SOURCE_DIR}) +target_compile_definitions(test_chowdsp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) -add_executable(test_chowsdp_fft_c test.c ${pffft_SOURCE_DIR}/pffft.c) -target_link_libraries(test_chowsdp_fft_c PRIVATE chowdsp_fft) -target_include_directories(test_chowsdp_fft_c PRIVATE ${pffft_SOURCE_DIR}) -target_compile_definitions(test_chowsdp_fft_c PRIVATE _USE_MATH_DEFINES=1) +add_executable(test_chowdsp_fft_c test.c ${pffft_SOURCE_DIR}/pffft.c) +target_link_libraries(test_chowdsp_fft_c PRIVATE chowdsp_fft) +target_include_directories(test_chowdsp_fft_c PRIVATE ${pffft_SOURCE_DIR}) +target_compile_definitions(test_chowdsp_fft_c PRIVATE _USE_MATH_DEFINES=1) From d7d902ea4d1b8951bd9cf6edcc86beab8bb1de17 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 20:21:44 -0700 Subject: [PATCH 06/17] More CI fixes --- bench/bench.cpp | 15 +++++++++++++++ test/test.cpp | 2 ++ 2 files changed, 17 insertions(+) diff --git a/bench/bench.cpp b/bench/bench.cpp index d4bbfac..8933a9e 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -2,11 +2,20 @@ #include #include #include +#include +#include #include #include #include +// @TODO: +// These benchmark results are not very reliable at the moment. +// In particular the timings for small FFT sizes are way too noisy +// to get any meaningful info from. At the very least we should +// take an average from a bunch of runs. Maybe it's worth it +// to use a fully-fledged benchmarking framework like google/benchmark? + std::pair bench_complex (int N) { static constexpr int M = 50; @@ -47,6 +56,9 @@ std::pair bench_complex (int N) auto ref_duration_seconds = std::chrono::duration (duration).count(); std::cout << " pffft: " << ref_duration_seconds << " seconds" << std::endl; + const auto speed_factor = ref_duration_seconds / test_duration_seconds; + std::cout << " speed: " << speed_factor << "x" << std::endl; + chowdsp::fft::fft_destroy_setup (fft_setup); pffft_destroy_setup (pffft_setup); chowdsp::fft::aligned_free (data); @@ -96,6 +108,9 @@ std::pair bench_real (int N) auto ref_duration_seconds = std::chrono::duration (duration).count(); std::cout << " pffft: " << ref_duration_seconds << " seconds" << std::endl; + const auto speed_factor = ref_duration_seconds / test_duration_seconds; + std::cout << " speed: " << speed_factor << "x" << std::endl; + chowdsp::fft::fft_destroy_setup (fft_setup); pffft_destroy_setup (pffft_setup); chowdsp::fft::aligned_free (data); diff --git a/test/test.cpp b/test/test.cpp index 784bdac..3c963e9 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1,3 +1,5 @@ +#include + #include #include From 8fafd3715251cc8dec8b747fba98be0f96ffe266 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 20:25:09 -0700 Subject: [PATCH 07/17] Missing header? --- README.md | 3 +++ bench/bench.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 69b6f13..9ae3f54 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # chowdsp_fft +[![Test](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/test.yml/badge.svg)](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/test.yml) +[![Bench](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/bench.yml/badge.svg)](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/bench.yml) + `chowdsp_fft` is a fork of the [`pffft`](https://bitbucket.org/jpommier/pffft/src/master/) library for computing Fast Fourier Transforms. This fork adds a couple of optimizations, most importantly the ability to use AVX intrinsics diff --git a/bench/bench.cpp b/bench/bench.cpp index 8933a9e..871394f 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -2,8 +2,9 @@ #include #include #include -#include +#include #include +#include #include #include From ab5cee2b8eb4374ec0658f4e34e8d6c4377d43c3 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 23:36:20 -0700 Subject: [PATCH 08/17] Test coverage? --- .github/workflows/test.yml | 21 ++++++++++++++++++++- CMakeLists.txt | 2 -- test/CMakeLists.txt | 8 ++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9dc4e1f..758ec6a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: include: - name: Linux os: ubuntu-22.04 - cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15" + cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DCHOWDSP_FFT_COVERAGE=ON" nparallel: 4 - name: Windows os: windows-2022 @@ -88,3 +88,22 @@ jobs: - name: Run Test C++ (Release) run: ./build/test/Release/test_chowdsp_fft_cpp + + - name: Collect Coverage Data + if: runner.os == 'Linux' + run: | + lcov --directory . --capture --output-file coverage.info + lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' '/Applications/Xcode*' '*build*' '*test*' --output-file coverage.info + + - name: Report Coverage Data + if: runner.os == 'Linux' + run: lcov --list coverage.info + + - name: Upload coverage to Codecov + if: runner.os == 'Linux' + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.info + verbose: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 540ffd2..bee64ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.20) project(chowdsp_fft) - set(CMAKE_CXX_STANDARD 20) -#set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") add_library(chowdsp_fft STATIC) target_sources(chowdsp_fft diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 34caf5e..5364670 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,6 +10,14 @@ target_link_libraries(test_chowdsp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2Wit target_include_directories(test_chowdsp_fft_cpp PRIVATE ${pffft_SOURCE_DIR}) target_compile_definitions(test_chowdsp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) +if(CHOWDSP_FFT_COVERAGE) + message(STATUS "chowdsp_fft -- Appending code coverage compiler flags: -g --coverage") + target_compile_options(chowdsp_fft_avx PUBLIC -g --coverage) + target_compile_options(chowdsp_fft PUBLIC -g --coverage) + target_compile_options(test_chowdsp_fft_cpp PUBLIC -O0 -g --coverage) + target_link_options(test_chowdsp_fft_cpp PUBLIC --coverage) +endif() + add_executable(test_chowdsp_fft_c test.c ${pffft_SOURCE_DIR}/pffft.c) target_link_libraries(test_chowdsp_fft_c PRIVATE chowdsp_fft) target_include_directories(test_chowdsp_fft_c PRIVATE ${pffft_SOURCE_DIR}) From 26790133cd2578b3b86f020e4f3a736b70a2ef6a Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 23:41:00 -0700 Subject: [PATCH 09/17] Separate coverage CI --- .github/workflows/bench.yml | 3 -- .github/workflows/coverage.yml | 61 ++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 24 +------------ bench/CMakeLists.txt | 2 +- 4 files changed, 63 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index aee06c8..bd4805e 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -64,9 +64,6 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - with: - submodules: recursive - token: ${{ secrets.OUR_GITHUB_PAT }} - name: Cmake Configure run: cmake -Bbuild -G"Ninja Multi-Config" -DCHOWDSP_FFT_TESTING=ON ${{ matrix.cmake_args }} diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..afb0123 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,61 @@ +name: Test + +on: + pull_request: + branches: + - main + - develop + push: + branches: + - ci + + workflow_dispatch: + +jobs: + build_and_test: + name: Test library with coverage + runs-on: ubuntu-22.04 + + steps: + - name: Install Linux Deps + run: | + sudo apt-get update + sudo apt install libasound2-dev libcurl4-openssl-dev libx11-dev libxinerama-dev libxext-dev libfreetype6-dev libwebkit2gtk-4.0-dev libglu1-mesa-dev libjack-jackd2-dev + sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" + sudo apt install clang-15 -y + + - name: Install Ninja + uses: seanmiddleditch/gha-setup-ninja@master + + - name: Get latest CMake + uses: lukka/get-cmake@latest + + - uses: rui314/setup-mold@v1 + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Cmake Configure + run: cmake -Bbuild -G"Ninja Multi-Config" -DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DCHOWDSP_FFT_TESTING=ON -DCHOWDSP_FFT_COVERAGE=ON + + - name: Build Test + run: cmake --build build --config Debug --parallel --target test_chowdsp_fft_cpp + + - name: Run Test + run: ./build/test/Debug/test_chowdsp_fft_cpp + + - name: Collect Coverage Data + run: | + lcov --directory . --capture --output-file coverage.info + lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' '/Applications/Xcode*' '*build*' '*test*' --output-file coverage.info + + - name: Report Coverage Data + run: lcov --list coverage.info + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.info + verbose: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 758ec6a..82e1e77 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: include: - name: Linux os: ubuntu-22.04 - cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DCHOWDSP_FFT_COVERAGE=ON" + cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15" nparallel: 4 - name: Windows os: windows-2022 @@ -64,9 +64,6 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - with: - submodules: recursive - token: ${{ secrets.OUR_GITHUB_PAT }} - name: Cmake Configure run: cmake -Bbuild -G"Ninja Multi-Config" -DCHOWDSP_FFT_TESTING=ON ${{ matrix.cmake_args }} @@ -88,22 +85,3 @@ jobs: - name: Run Test C++ (Release) run: ./build/test/Release/test_chowdsp_fft_cpp - - - name: Collect Coverage Data - if: runner.os == 'Linux' - run: | - lcov --directory . --capture --output-file coverage.info - lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' '/Applications/Xcode*' '*build*' '*test*' --output-file coverage.info - - - name: Report Coverage Data - if: runner.os == 'Linux' - run: lcov --list coverage.info - - - name: Upload coverage to Codecov - if: runner.os == 'Linux' - uses: codecov/codecov-action@v4 - with: - fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.info - verbose: true diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index a27959e..91a738a 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -1,4 +1,4 @@ -message(STATUS "chowdsp_fft -- Configuring benchmarks ${CMAKE_BINARY_DIR}/_deps/pffft-src") +message(STATUS "chowdsp_fft -- Configuring benchmarks") add_executable(bench_chowdsp_fft bench.cpp) target_link_libraries(bench_chowdsp_fft PRIVATE chowdsp_fft) From 5eef43291bfa80fdeb97f44c41b0b6b7e32ef612 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 14 Oct 2024 23:48:39 -0700 Subject: [PATCH 10/17] Trying to fix coverage --- .github/workflows/coverage.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index afb0123..7f34df6 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,4 +1,4 @@ -name: Test +name: Coverage on: pull_request: @@ -14,16 +14,39 @@ on: jobs: build_and_test: name: Test library with coverage - runs-on: ubuntu-22.04 + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false # show all errors for each platform (vs. cancel jobs on error) + matrix: + include: + - name: Linux + os: ubuntu-22.04 + cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15" + nparallel: 4 + - name: MacOS + os: macos-14 + cmake_args: "-D\"CMAKE_OSX_ARCHITECTURES=arm64;x86_64\"" + nparallel: 4 steps: - name: Install Linux Deps + if: runner.os == 'Linux' run: | sudo apt-get update sudo apt install libasound2-dev libcurl4-openssl-dev libx11-dev libxinerama-dev libxext-dev libfreetype6-dev libwebkit2gtk-4.0-dev libglu1-mesa-dev libjack-jackd2-dev sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" sudo apt install clang-15 -y + - name: Install lcov (Linux) + if: runner.os == 'Linux' + run: sudo apt install lcov + + - name: Install lcov (Mac) + if: runner.os == 'MacOS' + run: | + export HOMEBREW_NO_AUTO_UPDATE=1 + brew install lcov + - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@master @@ -31,12 +54,13 @@ jobs: uses: lukka/get-cmake@latest - uses: rui314/setup-mold@v1 + if: runner.os == 'Linux' - name: Checkout code uses: actions/checkout@v2 - name: Cmake Configure - run: cmake -Bbuild -G"Ninja Multi-Config" -DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DCHOWDSP_FFT_TESTING=ON -DCHOWDSP_FFT_COVERAGE=ON + run: cmake -Bbuild -G"Ninja Multi-Config" ${{ matrix.cmake_args }} -DCHOWDSP_FFT_TESTING=ON -DCHOWDSP_FFT_COVERAGE=ON - name: Build Test run: cmake --build build --config Debug --parallel --target test_chowdsp_fft_cpp From 8ca4c1a0a1c1ef67792b17f56e0e937ce255ebec Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 15 Oct 2024 00:11:41 -0700 Subject: [PATCH 11/17] Trying to ignore errors --- .github/workflows/coverage.yml | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7f34df6..b3d347f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -70,7 +70,7 @@ jobs: - name: Collect Coverage Data run: | - lcov --directory . --capture --output-file coverage.info + lcov --directory . --ignore-errors gcov --capture --output-file coverage.info lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' '/Applications/Xcode*' '*build*' '*test*' --output-file coverage.info - name: Report Coverage Data diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5364670..e62a153 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,7 +14,7 @@ if(CHOWDSP_FFT_COVERAGE) message(STATUS "chowdsp_fft -- Appending code coverage compiler flags: -g --coverage") target_compile_options(chowdsp_fft_avx PUBLIC -g --coverage) target_compile_options(chowdsp_fft PUBLIC -g --coverage) - target_compile_options(test_chowdsp_fft_cpp PUBLIC -O0 -g --coverage) + target_compile_options(test_chowdsp_fft_cpp PUBLIC -g --coverage) target_link_options(test_chowdsp_fft_cpp PUBLIC --coverage) endif() From f2e4b1d4e06f4d0a2be86e3b3dd8c17a4abe417f Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 15 Oct 2024 00:18:16 -0700 Subject: [PATCH 12/17] More coverage stuff --- .github/workflows/coverage.yml | 3 ++- test/CMakeLists.txt | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index b3d347f..3e11e65 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -70,7 +70,8 @@ jobs: - name: Collect Coverage Data run: | - lcov --directory . --ignore-errors gcov --capture --output-file coverage.info + lcov --version + llvm-cov gcov --directory . --capture --output-file coverage.info lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' '/Applications/Xcode*' '*build*' '*test*' --output-file coverage.info - name: Report Coverage Data diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e62a153..245f1ef 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,9 +12,9 @@ target_compile_definitions(test_chowdsp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) if(CHOWDSP_FFT_COVERAGE) message(STATUS "chowdsp_fft -- Appending code coverage compiler flags: -g --coverage") - target_compile_options(chowdsp_fft_avx PUBLIC -g --coverage) - target_compile_options(chowdsp_fft PUBLIC -g --coverage) - target_compile_options(test_chowdsp_fft_cpp PUBLIC -g --coverage) + target_compile_options(chowdsp_fft_avx PUBLIC -g --coverage -fprofile-arcs -ftest-coverage) + target_compile_options(chowdsp_fft PUBLIC -g --coverage -fprofile-arcs -ftest-coverage) + target_compile_options(test_chowdsp_fft_cpp PUBLIC -g --coverage -fprofile-arcs -ftest-coverage) target_link_options(test_chowdsp_fft_cpp PUBLIC --coverage) endif() From 44a83723e94ca7a11e4085737058a98f6713d473 Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 15 Oct 2024 00:21:35 -0700 Subject: [PATCH 13/17] Reset lcov command --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 3e11e65..bb9969c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -71,7 +71,7 @@ jobs: - name: Collect Coverage Data run: | lcov --version - llvm-cov gcov --directory . --capture --output-file coverage.info + lcov --directory . --capture --output-file coverage.info lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' '/Applications/Xcode*' '*build*' '*test*' --output-file coverage.info - name: Report Coverage Data From 47fb677d53ebaa3a5ce1ea46fe4c491dcbbeccc3 Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 15 Oct 2024 00:28:26 -0700 Subject: [PATCH 14/17] Compile coverage with GCC on Linux --- .github/workflows/coverage.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bb9969c..8bc2e66 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -21,11 +21,9 @@ jobs: include: - name: Linux os: ubuntu-22.04 - cmake_args: "-DCMAKE_LINKER_TYPE=MOLD -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15" nparallel: 4 - name: MacOS os: macos-14 - cmake_args: "-D\"CMAKE_OSX_ARCHITECTURES=arm64;x86_64\"" nparallel: 4 steps: @@ -34,8 +32,6 @@ jobs: run: | sudo apt-get update sudo apt install libasound2-dev libcurl4-openssl-dev libx11-dev libxinerama-dev libxext-dev libfreetype6-dev libwebkit2gtk-4.0-dev libglu1-mesa-dev libjack-jackd2-dev - sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" - sudo apt install clang-15 -y - name: Install lcov (Linux) if: runner.os == 'Linux' @@ -60,7 +56,7 @@ jobs: uses: actions/checkout@v2 - name: Cmake Configure - run: cmake -Bbuild -G"Ninja Multi-Config" ${{ matrix.cmake_args }} -DCHOWDSP_FFT_TESTING=ON -DCHOWDSP_FFT_COVERAGE=ON + run: cmake -Bbuild -G"Ninja Multi-Config" -DCHOWDSP_FFT_TESTING=ON -DCHOWDSP_FFT_COVERAGE=ON - name: Build Test run: cmake --build build --config Debug --parallel --target test_chowdsp_fft_cpp From 72ee327cc51ce3250b4cbdaeb58b2bf784458c23 Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 15 Oct 2024 00:34:56 -0700 Subject: [PATCH 15/17] Skip MacOS coverage for now --- .github/workflows/coverage.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 8bc2e66..4e6cf8b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -22,9 +22,9 @@ jobs: - name: Linux os: ubuntu-22.04 nparallel: 4 - - name: MacOS - os: macos-14 - nparallel: 4 +# - name: MacOS +# os: macos-14 +# nparallel: 4 steps: - name: Install Linux Deps From c556ddc041fd7a94e93875d0cd94fa270cc83ae4 Mon Sep 17 00:00:00 2001 From: jatin Date: Tue, 15 Oct 2024 00:43:06 -0700 Subject: [PATCH 16/17] README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9ae3f54..fa1ec46 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Test](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/test.yml/badge.svg)](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/test.yml) [![Bench](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/bench.yml/badge.svg)](https://github.com/Chowdhury-DSP/chowdsp_fft/actions/workflows/bench.yml) +[![codecov](https://codecov.io/gh/Chowdhury-DSP/chowdsp_fft/graph/badge.svg?token=A5BJ6CS859)](https://codecov.io/gh/Chowdhury-DSP/chowdsp_fft) `chowdsp_fft` is a fork of the [`pffft`](https://bitbucket.org/jpommier/pffft/src/master/) library for computing Fast Fourier Transforms. This fork adds a couple From d77d20579414f65dbd4fc20283c0915de05852e2 Mon Sep 17 00:00:00 2001 From: jatin Date: Wed, 16 Oct 2024 16:22:24 -0700 Subject: [PATCH 17/17] Friendlier C++ versioning --- CMakeLists.txt | 4 +++- bench/CMakeLists.txt | 1 + test/CMakeLists.txt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bee64ba..9f0c3ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.20) project(chowdsp_fft) -set(CMAKE_CXX_STANDARD 20) add_library(chowdsp_fft STATIC) target_sources(chowdsp_fft @@ -10,6 +9,7 @@ target_sources(chowdsp_fft ) target_include_directories(chowdsp_fft PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(chowdsp_fft PRIVATE _USE_MATH_DEFINES=1) +target_compile_features(chowdsp_fft PRIVATE cxx_std_17) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("/arch:AVX2" COMPILER_OPT_ARCH_AVX_MSVC_SUPPORTED) @@ -19,6 +19,7 @@ if(COMPILER_OPT_ARCH_AVX_MSVC_SUPPORTED) add_library(chowdsp_fft_avx STATIC simd/chowdsp_fft_impl_avx.cpp) target_compile_options(chowdsp_fft_avx PRIVATE /arch:AVX2) target_compile_definitions(chowdsp_fft_avx PRIVATE _USE_MATH_DEFINES=1) + target_compile_features(chowdsp_fft_avx PRIVATE cxx_std_17) target_link_libraries(chowdsp_fft PRIVATE chowdsp_fft_avx) target_compile_definitions(chowdsp_fft PRIVATE CHOWDSP_FFT_COMPILER_SUPPORTS_AVX=1) else() @@ -26,6 +27,7 @@ else() message(STATUS "chowdsp_fft -- Compiler supports flags: -mavx2 -mfma") add_library(chowdsp_fft_avx STATIC simd/chowdsp_fft_impl_avx.cpp) target_compile_options(chowdsp_fft_avx PRIVATE -mavx2 -mfma -Wno-unused-command-line-argument) + target_compile_features(chowdsp_fft_avx PRIVATE cxx_std_17) target_compile_definitions(chowdsp_fft_avx PRIVATE _USE_MATH_DEFINES=1) target_link_libraries(chowdsp_fft PRIVATE chowdsp_fft_avx) target_compile_definitions(chowdsp_fft PRIVATE CHOWDSP_FFT_COMPILER_SUPPORTS_AVX=1) diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index 91a738a..e87591e 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -4,3 +4,4 @@ add_executable(bench_chowdsp_fft bench.cpp) target_link_libraries(bench_chowdsp_fft PRIVATE chowdsp_fft) target_include_directories(bench_chowdsp_fft PRIVATE ${CMAKE_BINARY_DIR}/_deps/pffft-src) target_compile_definitions(bench_chowdsp_fft PRIVATE _USE_MATH_DEFINES=1) +target_compile_features(bench_chowdsp_fft PRIVATE cxx_std_20) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 245f1ef..9a510ed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,6 +9,7 @@ add_executable(test_chowdsp_fft_cpp test.cpp ${pffft_SOURCE_DIR}/pffft.c) target_link_libraries(test_chowdsp_fft_cpp PRIVATE chowdsp_fft Catch2::Catch2WithMain) target_include_directories(test_chowdsp_fft_cpp PRIVATE ${pffft_SOURCE_DIR}) target_compile_definitions(test_chowdsp_fft_cpp PRIVATE _USE_MATH_DEFINES=1) +target_compile_features(test_chowdsp_fft_cpp PRIVATE cxx_std_20) if(CHOWDSP_FFT_COVERAGE) message(STATUS "chowdsp_fft -- Appending code coverage compiler flags: -g --coverage")