From 41a9f421af4a96afe82fb3553ed6302d8ef2892f Mon Sep 17 00:00:00 2001 From: TheodorDM Date: Thu, 21 Aug 2025 19:55:36 +0300 Subject: [PATCH 1/4] core for GaussFiltr is reduced --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 1ffe97a..c335d99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,7 @@ int main() { { BMP bmp((base_path + "RotatedClockwise.bmp").c_str()); - bmp.GaussFiltr(39); // Используйте нечетный размер ядра + bmp.GaussFiltr(25); // Используйте нечетный размер ядра bmp.write((base_path + "GFiltr.bmp").c_str()); } From 929dee3061bc7e84d94a335539fc76babfc49434 Mon Sep 17 00:00:00 2001 From: TheodorDM Date: Thu, 21 Aug 2025 20:10:03 +0300 Subject: [PATCH 2/4] feat: there are timers for rotate-functions and gaussFiltr --- src/GaussFiltr.cpp | 7 +++++++ src/Rotate.cpp | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/GaussFiltr.cpp b/src/GaussFiltr.cpp index 94f3940..e237fa1 100644 --- a/src/GaussFiltr.cpp +++ b/src/GaussFiltr.cpp @@ -5,9 +5,12 @@ #include #include #include +#include void BMP::GaussFiltr(float kernelSize) { + auto start = std::chrono::high_resolution_clock::now(); + float sigma = (bmp_info_header.width + bmp_info_header.height - 2 * kernelSize)/4; std::vector> ratio(kernelSize, std::vector(kernelSize)); @@ -61,4 +64,8 @@ void BMP::GaussFiltr(float kernelSize) } data.swap(new_data); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + std::cout << "Gaussian filter time: " << duration.count() << " ms" << std::endl; } diff --git a/src/Rotate.cpp b/src/Rotate.cpp index 8207b2c..86abc15 100644 --- a/src/Rotate.cpp +++ b/src/Rotate.cpp @@ -4,10 +4,13 @@ #include #include #include +#include void BMP::clockwiseRotate() { + auto start = std::chrono::high_resolution_clock::now(); + int new_width = bmp_info_header.height; int new_height = bmp_info_header.width; @@ -36,10 +39,16 @@ void BMP::clockwiseRotate() bmp_info_header.width = new_width; bmp_info_header.height = new_height; data.swap(new_data); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + std::cout << "Clockwise rotation time: " << duration.count() << " ms" << std::endl; }; void BMP::CounterClockwiseRotate() { + auto start = std::chrono::high_resolution_clock::now(); + int new_width = bmp_info_header.height; int new_height = bmp_info_header.width; @@ -68,4 +77,8 @@ void BMP::CounterClockwiseRotate() bmp_info_header.width = new_width; bmp_info_header.height = new_height; data.swap(new_data); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + std::cout << "Counter-clockwise rotation time: " << duration.count() << " ms" << std::endl; } From 0be8dbe21fa0b68e2be09ca86f9af88c30d0dec3 Mon Sep 17 00:00:00 2001 From: TheodorDM Date: Sat, 23 Aug 2025 16:07:01 +0300 Subject: [PATCH 3/4] feat: parallelism is realised --- Makefile | 8 +++----- PerformReport.md | 9 +++++++++ src/BMP.h | 2 +- src/GaussFiltr.cpp | 18 ++++++++++++------ src/Rotate.cpp | 18 +++++++++--------- 5 files changed, 34 insertions(+), 21 deletions(-) create mode 100644 PerformReport.md diff --git a/Makefile b/Makefile index 7660fb2..a821cf4 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PROJECT = editBMP CXX = g++ -CXXFLAGS = -Isrc -std=c++17 -Werror -Wpedantic -Wall -g -fPIC +CXXFLAGS = -Isrc -std=c++17 -Wall -fopenmp SRC_DIR = src IMAGES_DIR = images @@ -13,9 +13,7 @@ OBJS = $(patsubst $(SRC_DIR)/%.cpp, %.o, $(SRCS)) default: all -all: $(PROJECT) images - -images: +all: $(PROJECT) mkdir -p $(IMAGES_DIR) %.o: $(SRC_DIR)/%.cpp $(DEPS) @@ -23,7 +21,7 @@ images: $(PROJECT): $(OBJS) $(CXX) -o $@ $^ $(CXXFLAGS) - + clean: rm -f *.o rm -f $(PROJECT) diff --git a/PerformReport.md b/PerformReport.md new file mode 100644 index 0000000..c046911 --- /dev/null +++ b/PerformReport.md @@ -0,0 +1,9 @@ +## Performance Report +# Report before realization of parallelism +Clockwise rotation time: 131 ms +Counter-clockwise rotation time: 123 ms +Gaussian filter time: 94309 ms +# Report with parallelism +Clockwise rotation time: 49,66 ms +Counter-clockwise rotation time: 47,33 ms +Gaussian filter time: 19038,33 ms diff --git a/src/BMP.h b/src/BMP.h index e3959ee..1a8d5f1 100644 --- a/src/BMP.h +++ b/src/BMP.h @@ -52,7 +52,7 @@ struct BMP { void clockwiseRotate(); void CounterClockwiseRotate(); - void GaussFiltr(float kernelSize); + void GaussFiltr(int kernelSize); BMP(const char *fname) { diff --git a/src/GaussFiltr.cpp b/src/GaussFiltr.cpp index e237fa1..7c5b07e 100644 --- a/src/GaussFiltr.cpp +++ b/src/GaussFiltr.cpp @@ -6,8 +6,9 @@ #include #include #include +#include -void BMP::GaussFiltr(float kernelSize) +void BMP::GaussFiltr(int kernelSize) { auto start = std::chrono::high_resolution_clock::now(); @@ -16,6 +17,7 @@ void BMP::GaussFiltr(float kernelSize) std::vector> ratio(kernelSize, std::vector(kernelSize)); double sum = 0.0; + // Вычисление ядра фильтра (последовательно) for (int x = 0; x < kernelSize; x++) { for (int y = 0; y < kernelSize; y++) @@ -28,6 +30,8 @@ void BMP::GaussFiltr(float kernelSize) sum += GaussFun; } } + + // Нормализация ядра for (int x = 0; x < kernelSize; x++) { for (int y = 0; y < kernelSize; y++) @@ -35,18 +39,20 @@ void BMP::GaussFiltr(float kernelSize) ratio[x][y] /= sum; } } - std::vector new_data(data); // Инициализация копией исходных данных + + std::vector new_data(data); - for (int i = kernelSize / 2; i <= bmp_info_header.width - kernelSize / 2; i++) + // Параллелизация применения фильтра + #pragma omp parallel for + for (int j = kernelSize / 2; j <= bmp_info_header.height - kernelSize / 2; j++) { - for (int j = kernelSize / 2; j <= bmp_info_header.height - kernelSize / 2; j++) + for (int i = kernelSize / 2; i <= bmp_info_header.width - kernelSize / 2; i++) { float blueSum = 0, greenSum = 0, redSum = 0; for (int k = 0; k < kernelSize; k++) { for (int l = 0; l < kernelSize; l++) { - // Исправление индексации: k - вертикаль, l - горизонталь int x_index = i + l - kernelSize / 2; int y_index = j + k - kernelSize / 2; int pixelIndex = (y_index * bmp_info_header.width + x_index) * 3; @@ -64,7 +70,7 @@ void BMP::GaussFiltr(float kernelSize) } data.swap(new_data); - + auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); std::cout << "Gaussian filter time: " << duration.count() << " ms" << std::endl; diff --git a/src/Rotate.cpp b/src/Rotate.cpp index 86abc15..b5dbf13 100644 --- a/src/Rotate.cpp +++ b/src/Rotate.cpp @@ -5,29 +5,29 @@ #include #include #include - +#include void BMP::clockwiseRotate() { auto start = std::chrono::high_resolution_clock::now(); - + int new_width = bmp_info_header.height; int new_height = bmp_info_header.width; std::vector new_data(new_width * new_height * 3); + // Параллелизация вращения + #pragma omp parallel for for (int y = 0; y < bmp_info_header.height; ++y) { for (int x = 0; x < bmp_info_header.width; ++x) { int old_index = (y * bmp_info_header.width + x) * 3; - int new_x, new_y; new_x = y; new_y = new_height - 1 - x; - int new_index = (new_y * new_width + new_x) * 3; new_data[new_index] = data[old_index]; @@ -39,7 +39,7 @@ void BMP::clockwiseRotate() bmp_info_header.width = new_width; bmp_info_header.height = new_height; data.swap(new_data); - + auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); std::cout << "Clockwise rotation time: " << duration.count() << " ms" << std::endl; @@ -48,24 +48,24 @@ void BMP::clockwiseRotate() void BMP::CounterClockwiseRotate() { auto start = std::chrono::high_resolution_clock::now(); - + int new_width = bmp_info_header.height; int new_height = bmp_info_header.width; std::vector new_data(new_width * new_height * 3); + // Параллелизация вращения + #pragma omp parallel for for (int y = 0; y < bmp_info_header.height; ++y) { for (int x = 0; x < bmp_info_header.width; ++x) { int old_index = (y * bmp_info_header.width + x) * 3; - int new_x, new_y; new_x = new_width - 1 - y; new_y = x; - int new_index = (new_y * new_width + new_x) * 3; new_data[new_index] = data[old_index]; @@ -77,7 +77,7 @@ void BMP::CounterClockwiseRotate() bmp_info_header.width = new_width; bmp_info_header.height = new_height; data.swap(new_data); - + auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); std::cout << "Counter-clockwise rotation time: " << duration.count() << " ms" << std::endl; From c958f953124f10f03edb591a49f5664435f385ea Mon Sep 17 00:00:00 2001 From: TheodorDM Date: Sat, 23 Aug 2025 17:08:07 +0300 Subject: [PATCH 4/4] feat: report is added --- PerformReport.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/PerformReport.md b/PerformReport.md index c046911..72de20e 100644 --- a/PerformReport.md +++ b/PerformReport.md @@ -1,9 +1,18 @@ -## Performance Report -# Report before realization of parallelism -Clockwise rotation time: 131 ms -Counter-clockwise rotation time: 123 ms -Gaussian filter time: 94309 ms -# Report with parallelism -Clockwise rotation time: 49,66 ms -Counter-clockwise rotation time: 47,33 ms -Gaussian filter time: 19038,33 ms +# Performance Report + + +### Test Configuration +- **CPU**: 6-core processor +- **Test Image**: 3840x2160 pixels +- **Threads**: 6 worker threads +- **Gaussian Kernel**: 25×25 (sigma = 1487,5) + + +| Operation | Single-Thread* | Multi-Thread** | Speedup | +|--------------------|----------------|----------------|---------| +| Clockwise | 231,00 ms | 49,66 ms | 4,65x | +| Counter-clockwise | 201,00 ms | 47,33 ms | 4,24x | +| Gaussian Filter | 85297,66 ms | 19038,33 ms | 4,48x | + +*Is calculated as an average of three runs of condition stored in the main branch +**Is calculated as an average of three runs of condition stored in current branch