From 8aa0dee3d102d85b2545dab5f6b082c00f24ad27 Mon Sep 17 00:00:00 2001 From: Claude Heiland-Allen Date: Tue, 27 Sep 2022 13:19:04 +0100 Subject: [PATCH 1/2] parallelize synapse generation using OpenMP - only tested on Debian Linux with a 16-thread amd64 CPU - Windows may need DLLs to be shipped with the EXE - using `-fopenmp` should be made optional via qmake somehow (without the flag, parallelization pragmas are ignored and it reverts to serial operation) - assumes `status::update()` among other code is thread-safe, it seems to work on my machine without issues... --- brain/src/brain.cpp | 25 +++++++++++++++---------- samplebrain.pro | 4 ++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/brain/src/brain.cpp b/brain/src/brain.cpp index b57db1b..0f4d2e8 100644 --- a/brain/src/brain.cpp +++ b/brain/src/brain.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -242,10 +243,12 @@ void brain::build_synapses_thresh(search_params ¶ms, double thresh) { m_average_error = calc_average_diff(params)*thresh; double err = m_average_error*thresh; u32 brain_size = m_blocks.size(); - u32 outer_index = 0; - for (auto &i : m_blocks) { + std::atomic progress{0}; + #pragma omp parallel for + for (u32 outer_index = 0; outer_index < brain_size; ++outer_index) { + auto &i = m_blocks[outer_index]; u32 index = 0; - status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); + status::update("building synapses %d%%",(int)(progress/(float)brain_size*100)); for (auto &j : m_blocks) { if (index!=outer_index) { // collect connections that are under threshold in closeness @@ -256,30 +259,32 @@ void brain::build_synapses_thresh(search_params ¶ms, double thresh) { } ++index; } - ++outer_index; + ++progress; } } void brain::build_synapses_fixed(search_params ¶ms) { //m_average_error = calc_average_diff(params)*thresh; u32 brain_size = m_blocks.size(); - u32 outer_index = 0; u32 num_synapses = NUM_FIXED_SYNAPSES; if (num_synapses>=m_blocks.size()) num_synapses=m_blocks.size()-1; // need to stop the progress updates flooding osc u32 update_period = 100; - u32 update_tick = 0; - - for (auto &i:m_blocks) { + std::atomic update_tick{0}; + std::atomic progress{0}; + #pragma omp parallel for + for (u32 outer_index = 0; outer_index < brain_size; ++outer_index) { + auto &i = m_blocks[outer_index]; if (update_tick>update_period) { - status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); + status::update("building synapses %d%%",(int)(progress/(float)brain_size*100)); update_tick=0; } update_tick++; u32 index = 0; vector> collect; + collect.reserve(brain_size); // collect comparisons to all other blocks for (auto &j:m_blocks) { @@ -304,7 +309,7 @@ void brain::build_synapses_fixed(search_params ¶ms) { i.get_synapse().push_back(collect[n].first); } - ++outer_index; + ++progress; } status::update("Done: %d synapses grown for %d blocks",num_synapses*brain_size,brain_size); } diff --git a/samplebrain.pro b/samplebrain.pro index c7df563..03e4e46 100644 --- a/samplebrain.pro +++ b/samplebrain.pro @@ -44,9 +44,9 @@ SOURCES += app/MainWindow.cpp \ INCLUDEPATH += brain/src INCLUDEPATH += /usr/local/include INCLUDEPATH += /opt/homebrew/include -LIBS += -L.. -L/usr/local/lib -L/opt/homebrew/lib -lportaudio -lfftw3 -lsndfile -llo -ldl -lpthread -lm +LIBS += -L.. -L/usr/local/lib -L/opt/homebrew/lib -lportaudio -lfftw3 -lsndfile -llo -ldl -lpthread -lm -fopenmp -QMAKE_CXXFLAGS += -O3 -Wall -Wno-unused -std=c++11 +QMAKE_CXXFLAGS += -O3 -fopenmp -Wall -Wno-unused -std=c++11 # assets RESOURCES = app/samplebrain.qrc From fa44d2b4c714754f231df73af703469d986e9197 Mon Sep 17 00:00:00 2001 From: Dave Griffiths Date: Sat, 29 Oct 2022 13:13:16 +0100 Subject: [PATCH 2/2] added openmp to cmake --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71a5d5e..553445b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt5 REQUIRED COMPONENTS Core) find_package(Qt5 REQUIRED COMPONENTS Gui Widgets) +find_package(OpenMP) add_executable(samplebrain WIN32 MACOSX_BUNDLE app/MainWindow.cpp app/MainWindow.h @@ -64,6 +65,11 @@ target_link_libraries(samplebrain PRIVATE sndfile ) +if(OpenMP_CXX_FOUND) + target_link_libraries(samplebrain PUBLIC OpenMP::OpenMP_CXX) +endif() + + # Resources: set(samplebrain_resource_files "app/images/at.png"