-
Notifications
You must be signed in to change notification settings - Fork 80
Папулина Юлия. Технология SEQ-MPI. Подсчет числа буквенных символов в строке. Вариант 22 #25
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
Merged
allnes
merged 46 commits into
learning-process:master
from
ulillli:papulina_y_count_of_letters
Dec 10, 2025
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
9ac1ff2
Add papulina_y_count_of_letters task implementation
ulillli 2422cff
Trigger CI rebuild
ulillli 2fa34c6
Trigger CI rebuild
ulillli 0006422
some fixes for clang-format
ulillli 651c68e
some fixes for clang-format
ulillli d86ba06
function countofletters is changed
ulillli ecb46f8
clang-format fixes
ulillli ef4a179
fixed some bugs in the mpi version
ulillli c765324
some fixes for clang-format
ulillli fa4d6d7
fixed some bugs in the mpi version of task
ulillli faa6c48
Merge remote-tracking branch 'upstream/master' into papulina_y_count_…
ulillli 2569936
added cout for mpi
ulillli d0285a2
changed names of tests
ulillli 150e316
fixed clang-format
ulillli eb56fe5
added some tests for checking results
ulillli 36cea32
Merge remote-tracking branch 'upstream/master' into papulina_y_count_…
ulillli fba47d9
Merge remote-tracking branch 'upstream/master' into papulina_y_count_…
ulillli d35e56c
added some tests
ulillli 0452e06
added output info
ulillli 8e118e6
clang-format is fixed
ulillli a4a1309
added some fixes in MPI version
ulillli b37727c
fixed some bugs in MPI
ulillli 2a9a2b9
new MPI version checking
ulillli 77ba775
trying to use Barrier
ulillli 1de2e37
some fixes for coverage
ulillli 8f3ff92
[pre-commit] Update hooks versions
github-actions[bot] 8a7dcc4
added fixes in function countofletters
ulillli e82dd8d
Merge remote-tracking branch 'upstream/master' into papulina_y_count_…
ulillli 9f850a5
fixes for clang-tidy and romeved output info
ulillli 57a9d79
merge with update pre-commit-hooks
ulillli 07fe6f5
clang-format.......
ulillli f7559df
Merge remote-tracking branch 'origin/update-pre-commit-hooks' into pa…
ulillli b1f96a6
empty commit
ulillli 68c267b
deleted strange file
ulillli b91dc5f
Merge remote-tracking branch 'upstream/master' into branch_for_fixes
ulillli 6b2ca94
some fixes in mpi version and added generating of string
ulillli d683313
fixed clang-tidy
ulillli ad05246
deleted output info for perf tests
ulillli c5a188a
report is added
ulillli fdbdfe6
report is improved
ulillli e2bdd82
fixes in report
ulillli 9475696
last fixes in report
ulillli 9cb7e17
some fixes for clang-tidy
ulillli 6436e84
comments deleted
ulillli 30a8a32
checking on the empty string before resize
ulillli 845442d
accidental file pre-commit-config.yaml corrections are deleted
ulillli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
tasks/papulina_y_count_of_letters/common/include/common.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> | ||
| #include <tuple> | ||
|
|
||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace papulina_y_count_of_letters { | ||
|
|
||
| using InType = std::string; | ||
| using OutType = int; | ||
| using TestType = std::tuple<std::tuple<std::string, int>, std::string>; // патерн + длина строки | ||
| using BaseTask = ppc::task::Task<InType, OutType>; | ||
|
|
||
| } // namespace papulina_y_count_of_letters |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "student": { | ||
| "first_name": "Юлия", | ||
| "last_name": "Папулина", | ||
| "middle_name": "Андреевна", | ||
| "group_number": "3823Б1ФИ3", | ||
| "task_number": "1" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #pragma once | ||
|
|
||
| #include "papulina_y_count_of_letters/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace papulina_y_count_of_letters { | ||
|
|
||
| class PapulinaYCountOfLettersMPI : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kMPI; | ||
| } | ||
| explicit PapulinaYCountOfLettersMPI(const InType &in); | ||
|
|
||
| private: | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| static int CountOfLetters(const char *s, const int &n); | ||
|
|
||
| int procNum_ = 0; | ||
| }; | ||
|
|
||
| } // namespace papulina_y_count_of_letters |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| #include "papulina_y_count_of_letters/mpi/include/ops_mpi.hpp" | ||
|
|
||
| #include <mpi.h> | ||
|
|
||
| #include <algorithm> | ||
| #include <cctype> | ||
| #include <string> | ||
|
|
||
| #include "papulina_y_count_of_letters/common/include/common.hpp" | ||
|
|
||
| namespace papulina_y_count_of_letters { | ||
|
|
||
| PapulinaYCountOfLettersMPI::PapulinaYCountOfLettersMPI(const InType &in) { | ||
| SetTypeOfTask(GetStaticTypeOfTask()); | ||
| GetInput() = in; | ||
| GetOutput() = 0; | ||
| MPI_Comm_size(MPI_COMM_WORLD, &procNum_); | ||
| } | ||
| int PapulinaYCountOfLettersMPI::CountOfLetters(const char *s, const int &n) { | ||
| int k = 0; | ||
| if (n <= 0) { | ||
| return 0; | ||
| } | ||
| for (int i = 0; i < n; i++) { | ||
| char c = s[i]; | ||
| if (isalpha(c) != 0) { | ||
| k++; | ||
| } | ||
| } | ||
| return k; | ||
| } | ||
| bool PapulinaYCountOfLettersMPI::ValidationImpl() { | ||
| return procNum_ > 0; | ||
| } | ||
|
|
||
| bool PapulinaYCountOfLettersMPI::PreProcessingImpl() { | ||
| return true; | ||
| } | ||
|
|
||
| bool PapulinaYCountOfLettersMPI::RunImpl() { | ||
| int proc_rank = 0; | ||
| int result = 0; | ||
| std::string part_of_string; // части строки, которая будет обрабатываться потоком | ||
| unsigned int len = 0; // предполагаемая длина обрабатываемой части | ||
| unsigned int remainder = 0; // остаток, если длина строки не кратна числу потоков | ||
| unsigned int true_len = 0; // реальная длина обрабатываемой части | ||
| MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank); | ||
|
|
||
| if (proc_rank == 0) { | ||
| std::string s = GetInput(); | ||
|
|
||
|
allnes marked this conversation as resolved.
|
||
| len = s.size() / procNum_; | ||
| remainder = s.size() % procNum_; | ||
| MPI_Bcast(&len, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD); | ||
| MPI_Bcast(&remainder, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD); | ||
|
|
||
| unsigned int begin_0 = (0 * len) + std::min(static_cast<unsigned int>(0), remainder); | ||
| unsigned int end_0 = ((0 + 1) * len) + std::min(static_cast<unsigned int>(0 + 1), remainder); | ||
| true_len = end_0 - begin_0; | ||
| part_of_string = (true_len > 0) ? s.substr(begin_0, true_len) : ""; | ||
|
allnes marked this conversation as resolved.
|
||
|
|
||
| for (int i = 1; i < procNum_; i++) { | ||
| unsigned int begin = (i * len) + std::min(static_cast<unsigned int>(i), remainder); | ||
| unsigned int end = ((i + 1) * len) + std::min(static_cast<unsigned int>(i + 1), remainder); | ||
| unsigned int pre_true_len = end - begin; // предварительная длина обрабатываемой части | ||
|
|
||
| MPI_Send(&pre_true_len, 1, MPI_UNSIGNED, i, 0, MPI_COMM_WORLD); | ||
| if (end - begin != 0) { | ||
| MPI_Send(s.substr(begin, pre_true_len).data(), static_cast<int>(pre_true_len), MPI_CHAR, i, 1, MPI_COMM_WORLD); | ||
| } else { | ||
| MPI_Send("", 0, MPI_CHAR, i, 1, MPI_COMM_WORLD); | ||
| } | ||
| } | ||
| } else { | ||
| MPI_Bcast(&len, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD); | ||
| MPI_Bcast(&remainder, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD); | ||
| MPI_Recv(&true_len, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | ||
| if (true_len > 0) { | ||
| part_of_string.resize(true_len); | ||
| } | ||
| MPI_Recv(part_of_string.data(), static_cast<int>(true_len), MPI_CHAR, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); | ||
| } | ||
| int local_result = CountOfLetters(part_of_string.data(), static_cast<int>(part_of_string.size())); | ||
| MPI_Reduce(&local_result, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); | ||
| MPI_Bcast(&result, 1, MPI_INT, 0, MPI_COMM_WORLD); | ||
| GetOutput() = result; | ||
| MPI_Barrier(MPI_COMM_WORLD); | ||
| return true; | ||
| } | ||
|
|
||
| bool PapulinaYCountOfLettersMPI::PostProcessingImpl() { | ||
| return GetOutput() >= 0; | ||
| } | ||
|
|
||
| } // namespace papulina_y_count_of_letters | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| # Подсчет числа буквенных символов в строке | ||
|
|
||
| - Student: Папулина Юлия Андреевна, group 3823Б1ФИ3 | ||
| - Technology: SEQ | MPI | ||
| - Variant: 22 | ||
|
|
||
| ## 1. Введение | ||
| Задача подсчета буквенных символов в строке является одной из базовых операций в обработке текстовых данных и представляет собой идеальный пример для освоения принципов параллельного программирования. Сейчас, когда объемы обрабатываемой текстовой информации постоянно растут, эффективная реализация таких операций становится особенно важной. В рамках данной работы реализован MPI-алгоритм, демонстрирующий ключевые аспекты параллельного программирования: декомпозицию задачи, балансировку нагрузки и коллективные операции. | ||
|
|
||
| ## 2. Постановка задачи | ||
| **Формальная постановка:** для заданной строки S длиной N подсчитать количество символов, являющихся буквами латинского алфавита. | ||
|
|
||
| **Входные данные:** строка S произвольной длины | ||
|
|
||
| **Выходные данные:** целое число - количество буквенных символов | ||
|
|
||
| **Ограничения:** | ||
| - Решение должно быть масштабируемым для различного числа процессов | ||
|
|
||
| ## 3. Последовательная версия(Baseline) | ||
| Алгоритм последовательно проверяет каждый символ строки, определяя принадлежность к латинскому алфавиту с помощью функции int isalpha( int ch ) | ||
| ```cpp | ||
| int result = 0; | ||
| if (n <= 0) { | ||
| return 0; | ||
| } | ||
| for (int i = 0; i < n; i++) { | ||
| unsigned char c = s[i]; | ||
| if (isalpha(c) != 0) { | ||
| result++; | ||
| } | ||
| } | ||
| return result; | ||
| ``` | ||
|
|
||
| ## 4. Параллельная версия | ||
|
|
||
| ### 4.1. Разделение данных | ||
| Используется блочное распределение данных с равномерным распределением остатка: | ||
| - базовый размер блока: len = length / num_processes | ||
| - остаток: remainder = length % num_processes | ||
| - процесс i получает: len + (i < remainder ? 1 : 0) символов (таким образом, все ramainder процессов получат + дополнительный символ к обработке) | ||
|
|
||
| ### 4.2. Взаимодействие процессов | ||
| #### Процесс 0 (Координатор) | ||
| - читает входную строку | ||
| - рассылает базовый размер блока(len) и остаток(reminder) остальным потокам(MPI_Bcast) | ||
| - инициализирует свою часть обработки строки | ||
| - отправка данных(часть строки) для обработки другим процессам через for (MPI_Send) | ||
| - cобирает результаты (MPI_Reduce) | ||
|
|
||
| #### Процессы 1..N-1 (Рабочие процессы) | ||
| - получают параметры: размер блока, остаток(MPI_Bcast) | ||
| - получают свою часть строки для обработки(MPI_Recv) | ||
| - выполняют подсчет на своей части | ||
| - отправляют результат (MPI_Reduce) | ||
|
|
||
| ### 4.3. Псевдокод алгоритма | ||
| ```pseudocode | ||
| FUNCTION: | ||
| │ | ||
| ├─ INITIALIZATION | ||
| │ • Get process rank | ||
| │ • Initialize variables | ||
| │ | ||
| ├─ DATA DISTRIBUTION PHASE | ||
| │ │ | ||
| │ ├─ IF rank = 0 (MASTER): | ||
| │ │ • Read input string | ||
| │ │ • Calculate base_len = length / procNum | ||
| │ │ • Calculate remainder = length % procNum | ||
| │ │ • Broadcast base_len, remainder | ||
| │ │ • Counting the processed part for master | ||
| │ │ • For each worker i: | ||
| │ │ - Calculate chunk boundaries | ||
| │ │ - Send chunk_size | ||
| │ │ - Send chunk_data | ||
| │ │ | ||
| │ └─ ELSE (WORKER): | ||
| │ • Receive broadcast base_len, remainder | ||
| │ • Receive chunk_size | ||
| │ • Receive chunk_data | ||
| │ | ||
| ├─ COMPUTATION PHASE | ||
| │ • Each process: Count letters in local_data | ||
| │ | ||
| ├─ RESULT COLLECTION PHASE | ||
| │ • MPI_Reduce: SUM all local_count → process 0 | ||
| │ • Broadcast result | ||
| │ • Set result | ||
| │ | ||
| └─ RETURN success | ||
| ``` | ||
| ## 5. Детали реализации | ||
|
|
||
| ### 5.1. Файловая структура проекта | ||
| papulina_y_count_of_letters/ | ||
| ├── common/include/common.hpp | ||
| ├── seq/include/ops_seq.hpp | ||
| ├── seq/src/ops_seq.cpp | ||
| ├── mpi/include/ops_mpi.hpp | ||
| ├── mpi/src/ops_mpi.cpp | ||
| ├── tests/functional/main.cpp | ||
| ├── tests/performance/main.cpp | ||
| └── data/ | ||
|
|
||
| ### 5.2. Ключевые классы и функции | ||
|
|
||
| - `InType = std::string` - тип входных данных (строка) | ||
| - `OutType = int` - тип выходных данных (количество букв) | ||
| - `CountOfLetters(const char* s, const int& n)` - функция подсчета символов | ||
| - `RunImpl()` - основная логика последовательного выполнения | ||
| - `ValidationImpl()` - проверка валидности входных данных | ||
| - `PreProcessingImpl()` - подготовительные операции | ||
| - `PostProcessingImpl()` - завершающие операции | ||
| - `class PapulinaYRunFuncTestsProcesses` - параметрические функциональные тесты | ||
| - `class PapulinaYRunPerfTestsProcesses` - параметрические тесты производительности | ||
|
|
||
| ### 5.3. Использование памяти | ||
|
|
||
| **SEQ версия:** | ||
| - хранит всю входную строку в памяти | ||
| - O(N) память, где N - длина строки | ||
| - минимальные накладные расходы(отсутствуют затраты на синхронизацию между потоками/процессами) | ||
|
|
||
| **MPI версия:** | ||
| - процесс 0: хранит всю строку + буферы для коммуникации | ||
| - рабочие процессы: хранят только свою часть строки | ||
| - дополнительная память для MPI буферов сообщений | ||
| - эффективное распределение памяти при больших N | ||
|
|
||
| ## 6. Экспериментальное окружение | ||
|
|
||
| **Hardware/OS:** | ||
| - **CPU:** Intel Core i5-11400H (6 cores, 12 threads, 2.70 GHz base frequency) | ||
| - **RAM:** 16.0 GB DDR4 | ||
| - **Storage:** SSD 512 GB | ||
| - **OS:** Windows 10 | ||
|
|
||
| **Toolchain:** | ||
| - **Compiler:** Microsoft Visual C++ 2019 (MSVC 19.29.30153) | ||
| - **MPI Implementation:** Microsoft MPI Version10.1.12498.52 | ||
| - **Build System:** CMake 3.30.3 | ||
| - **Build Type:** Release | ||
|
|
||
| **Environment:** | ||
| - **PPC_NUM_PROC:** 1, 2, 4, 6 | ||
|
|
||
| **Data:** строка из 40 000 000 латинских символов | ||
|
|
||
| ## 7. Результаты | ||
|
|
||
| ### 7.1 Корректность | ||
| Корректность реализации была проверена через комплексную систему тестирования, включающую: | ||
| - 20 функциональных тестов(пустая строка, строка из одного символа, строка с генерированными символами) | ||
| - тест на производительность на стабильных данных | ||
|
|
||
| **Структура параметров теста:** | ||
| - строка (generate - если тест на генерацию) | ||
| - ожидаемый результат | ||
| - название теста(его номер) | ||
|
|
||
| ### 7.2 Производительность | ||
| Время выполнения для строки длиной 40 000 000 символов: | ||
|
|
||
| | Mode | Count | Time, s | Speedup | Efficiency | | ||
| |-------------|-------|---------|---------|------------| | ||
| | seq | 1 | 0.0951 | 1.00 | N/A | | ||
| | mpi | 2 | 0.0937 | 1.01 | 50.5% | | ||
| | mpi | 3 | 0.0718 | 1.32 | 44.0% | | ||
| | mpi | 4 | 0.0737 | 1.29 | 32.3% | | ||
| | mpi | 6 | 0.0778 | 1.22 | 20.3% | | ||
|
|
||
| **Анализ результатов:** | ||
| - минимальное ускорение: наблюдается незначительное ускорение (1.01-1.32x) даже при использовании нескольких процессов | ||
| - низкая эффективность: эффективность варьируется от 20.3% до 50.5%, что указывает на значительные накладные расходы | ||
| - оптимальная конфигурация: максимальное ускорение достигается при 3 процессах (1.32x) | ||
|
|
||
| **Анализ узких мест:** | ||
| - коммуникационные затраты: время передачи данных между процессами превышает время вычислений для данного объема данных | ||
| - неидеальное распределение: алгоритм распределения данных создает дополнительную нагрузку | ||
|
|
||
| ## 8. Заключение | ||
| В результате работы в учебных целях разработаны последовательная (SEQ) и параллельная (MPI) версии программы, подсчитывающей число латинских символов в строке. Несмотря на ограниченную практическую эффективность для конкретной задачи подсчета символов, реализация успешно демонстрирует принципы распределенных вычислений и может служить основой для более сложных алгоритмов обработки текста. | ||
|
|
||
| ## 9. Источники | ||
| 1. Microsoft MPI : документация [Электронный ресурс] // Microsoft Learn. – URL: https://learn.microsoft.com/ru-ru/message-passing-interface/microsoft-mpi (дата обращения: 03.11.2025). | ||
| 2. Сысоев А. В. Курс лекций по параллельному программированию |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #pragma once | ||
|
|
||
| #include "papulina_y_count_of_letters/common/include/common.hpp" | ||
| #include "task/include/task.hpp" | ||
|
|
||
| namespace papulina_y_count_of_letters { | ||
|
|
||
| class PapulinaYCountOfLettersSEQ : public BaseTask { | ||
| public: | ||
| static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { | ||
| return ppc::task::TypeOfTask::kSEQ; | ||
| } | ||
| explicit PapulinaYCountOfLettersSEQ(const InType &in); | ||
|
|
||
| private: | ||
| static int CountOfLetters(const char *s, const int &n); | ||
| bool ValidationImpl() override; | ||
| bool PreProcessingImpl() override; | ||
| bool RunImpl() override; | ||
| bool PostProcessingImpl() override; | ||
| }; | ||
|
|
||
| } // namespace papulina_y_count_of_letters |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.