Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions tasks/orehov_n_character_frequency/common/include/common.hpp
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 orehov_n_character_frequency {

using InType = std::tuple<std::string, std::string>;
using OutType = int;
using TestType = std::string;
using BaseTask = ppc::task::Task<InType, OutType>;

} // namespace orehov_n_character_frequency
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions tasks/orehov_n_character_frequency/data/string1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
qwezrtyuiozpasdfghjklzxcvbnmz
z
2 changes: 2 additions & 0 deletions tasks/orehov_n_character_frequency/data/string2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
qwezrtyuqioggggzpasdfghjklzxcvbnmzq
q
2 changes: 2 additions & 0 deletions tasks/orehov_n_character_frequency/data/string3.txt

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions tasks/orehov_n_character_frequency/info.json
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"
}
}
22 changes: 22 additions & 0 deletions tasks/orehov_n_character_frequency/mpi/include/ops_mpi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "orehov_n_character_frequency/common/include/common.hpp"
#include "task/include/task.hpp"

namespace orehov_n_character_frequency {

class OrehovNCharacterFrequencyMPI : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kMPI;
}
explicit OrehovNCharacterFrequencyMPI(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;
};

} // namespace orehov_n_character_frequency
94 changes: 94 additions & 0 deletions tasks/orehov_n_character_frequency/mpi/src/ops_mpi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "orehov_n_character_frequency/mpi/include/ops_mpi.hpp"

#include <mpi.h>

#include <algorithm>
#include <cstddef>
#include <string>
#include <tuple>
#include <vector>

#include "orehov_n_character_frequency/common/include/common.hpp"

namespace orehov_n_character_frequency {

OrehovNCharacterFrequencyMPI::OrehovNCharacterFrequencyMPI(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = 0;
}

bool OrehovNCharacterFrequencyMPI::ValidationImpl() {
return (!std::get<0>(GetInput()).empty()) && (std::get<1>(GetInput()).length() == 1);
}

bool OrehovNCharacterFrequencyMPI::PreProcessingImpl() {
return true;
}

bool OrehovNCharacterFrequencyMPI::RunImpl() {
int rank = 0;
int size = 0;

MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

std::string local_str;
std::string symbol;
int length = 0;
int global_result = 0;
int local_result = 0;

if (rank == 0) {
std::string str = std::get<0>(GetInput());
symbol = std::get<1>(GetInput());
length = static_cast<int>(str.length());
MPI_Bcast(symbol.data(), 1, MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Bcast(&length, 1, MPI_INT, 0, MPI_COMM_WORLD);

int part_size = length / size;
int remains = length % size;

std::vector<int> sendcounts(size);
std::vector<int> displs(size);

for (int i = 0; i < size; i++) {
sendcounts[i] = part_size + (i < remains ? 1 : 0);
displs[i] = (i * part_size) + std::min(i, remains);
}

local_str.resize(sendcounts[0]);

MPI_Scatterv(str.data(), sendcounts.data(), displs.data(), MPI_CHAR, local_str.data(), sendcounts[0], MPI_CHAR, 0,
MPI_COMM_WORLD);
} else {
symbol.resize(1);
MPI_Bcast(symbol.data(), 1, MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Bcast(&length, 1, MPI_INT, 0, MPI_COMM_WORLD);

int part_size = length / size;
int remains = length % size;

int local_size = part_size + (rank < remains ? 1 : 0);
local_str.resize(local_size);

MPI_Scatterv(nullptr, nullptr, nullptr, MPI_CHAR, local_str.data(), local_size, MPI_CHAR, 0, MPI_COMM_WORLD);
}

for (size_t i = 0; i < local_str.length(); i++) {
if (local_str[i] == symbol[0]) {
local_result++;
}
}

MPI_Allreduce(&local_result, &global_result, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
GetOutput() = global_result;

return true;
}

bool OrehovNCharacterFrequencyMPI::PostProcessingImpl() {
return true;
}

} // namespace orehov_n_character_frequency
106 changes: 106 additions & 0 deletions tasks/orehov_n_character_frequency/report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# отчёт

- задача 1
- вариант 23
- сделал: Орехов Никита Антонович
- группа: 3823Б1ПМоп3

## 1. Introduction
Задача заключается в подсчёте частоты определённого символа в строке.
Цель - реализовать последовательную и параллельную версию и сравнить их производительность.
Ожидание - выигрыш параллельной версии

## 2. Problem Statement
**Входные данные:**
- Строка (Берётся из файла)
- Целевой символ (Берётся из следующей строки в том же файле)

**Выходные данные:**

- Частота целевого символа в строке

**Ограничения**

- Строка не должна быть пустой
- Строка с целевым символом не должна быть пустой

## 3. Baseline Algorithm (Sequential)

В цикле проверяем на совпадение поочередно каждый символ.
При совпадении увеличиваем счётчик

## 4. Parallelization Scheme

Вначале считаем сколько данных получит каждый процесс. Распределяем их равномерно.
После каждый процесс считает частоту символа в своей части данных
Дальше с помощью MPI_AllReduce собираем данные и складываем их
И результат отправляется всем процессам

**Распределение данных:**

Данные делятся на равные части между процессами.
Оставшиеся данные распределяются равномерно между первыми процессами

**Шаблон коммуникаций**

Используется AllReduce для суммирования частот со всех процессов и отправки результата всем

**Роли процессов**

Все равны

## 5. Implementation Details

'''cpp
bool OrehovNCharacterFrequencyMPI::RunImpl() {
int rank, size;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

std::string str = std::get<0>(GetInput());
std::string symbol = std::get<1>(GetInput());
int length = str.length();

int part_size = length / size;
int remains = length % size;

int start = rank * part_size + std::min(rank, remains);
int end = (rank + 1) * part_size + std::min(rank + 1, remains);

int local_result = 0;

for (int i = start; i < end; i++){
if (str[i] == symbol[0]) local_result++;
}

int global_result = 0;

MPI_Allreduce(&local_result, &global_result, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
GetOutput() = global_result;

return true;
}
'''

## 6. Experimental Setup

- Процессор: Процессор Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz 2.40 GHz
- Количество ядер: 4
- RAM: 16
- OS Version: Windows 10


## 7. Performance

Mode | Count | Time, s | Speedup | Efficiency |
|-------------|-------|---------|---------|------------|
| seq | 1 | 0.04743 | 1.00 | N/A |
| omp | 4 | 0.05366 | 0.88 | 22% |


## 8. Conclusions

Параллельная версия показала замедление.
Основная причина в отсутствии вычислений, кроме счётчика.
Время MPI коммуникаций значительно преобладает над временем вычислений

22 changes: 22 additions & 0 deletions tasks/orehov_n_character_frequency/seq/include/ops_seq.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "orehov_n_character_frequency/common/include/common.hpp"
#include "task/include/task.hpp"

namespace orehov_n_character_frequency {

class OrehovNCharacterFrequencySEQ : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kSEQ;
}
explicit OrehovNCharacterFrequencySEQ(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;
};

} // namespace orehov_n_character_frequency
42 changes: 42 additions & 0 deletions tasks/orehov_n_character_frequency/seq/src/ops_seq.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "orehov_n_character_frequency/seq/include/ops_seq.hpp"

#include <cstddef>
#include <string>

#include "orehov_n_character_frequency/common/include/common.hpp"

namespace orehov_n_character_frequency {

OrehovNCharacterFrequencySEQ::OrehovNCharacterFrequencySEQ(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = 0;
}

bool OrehovNCharacterFrequencySEQ::ValidationImpl() {
return (!std::get<0>(GetInput()).empty()) && (std::get<1>(GetInput()).length() == 1);
}

bool OrehovNCharacterFrequencySEQ::PreProcessingImpl() {
return true;
}

bool OrehovNCharacterFrequencySEQ::RunImpl() {
std::string str = std::get<0>(GetInput());
std::string symbol = std::get<1>(GetInput());
int result = 0;
for (size_t i = 0; i < str.length(); i++) {
if (str[i] == symbol[0]) {
result++;
}
}
GetOutput() = result;

return true;
}

bool OrehovNCharacterFrequencySEQ::PostProcessingImpl() {
return true;
}

} // namespace orehov_n_character_frequency
7 changes: 7 additions & 0 deletions tasks/orehov_n_character_frequency/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"tasks_type": "processes",
"tasks": {
"mpi": "enabled",
"seq": "enabled"
}
}
13 changes: 13 additions & 0 deletions tasks/orehov_n_character_frequency/tests/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
InheritParentConfig: true

Checks: >
-modernize-loop-convert,
-cppcoreguidelines-avoid-goto,
-cppcoreguidelines-avoid-non-const-global-variables,
-misc-use-anonymous-namespace,
-modernize-use-std-print,
-modernize-type-traits
CheckOptions:
- key: readability-function-cognitive-complexity.Threshold
value: 50 # Relaxed for tests
Loading
Loading