final cleanup 1

This commit is contained in:
2026-04-28 15:15:10 +07:00
parent ea6d6f3d64
commit a6118b5787
2 changed files with 38 additions and 22 deletions
+10 -6
View File
@@ -94,19 +94,23 @@ def draw_gantt(ordered):
first = min(p.start for p in ordered) first = min(p.start for p in ordered)
# Создаем карту цветов, чтобы PID всегда имел один и тот же цвет
cmap = plt.get_cmap('tab20')
color_map = {p.pid: cmap(i % 20) for i, p in enumerate(ordered)}
# ------------------------- # -------------------------
# 1) TREE ORDER (current) # 1) TREE ORDER (current)
# ------------------------- # -------------------------
fig, ax = plt.subplots(figsize=(12, 6)) fig, ax = plt.subplots(figsize=(12, 6))
for i, p in enumerate(ordered): for i, p in enumerate(ordered):
ax.barh(i, p.duration, left=p.start - first, height=0.6) ax.barh(i, p.duration, left=p.start - first, height=0.6, color=color_map[p.pid])
ax.text(p.start - first, i, f"PID {p.pid} ({p.depth})", va="center") ax.text(p.start - first, i, f"PID {p.pid} ({p.depth})", va="center")
ax.set_yticks(range(len(ordered))) ax.set_yticks(range(len(ordered)))
ax.set_yticklabels([f"{p.pid} ({p.depth})" for p in ordered]) ax.set_yticklabels([f"{p.pid} ({p.depth})" for p in ordered])
ax.set_xlabel("Seconds from first process start") ax.set_xlabel("Секунд с начала первого процесса")
ax.set_title("Gantt (Tree Order)") ax.set_title("Диаграмма процессов (в виде дерева)")
ax.invert_yaxis() ax.invert_yaxis()
plt.tight_layout() plt.tight_layout()
@@ -121,13 +125,13 @@ def draw_gantt(ordered):
fig, ax = plt.subplots(figsize=(12, 6)) fig, ax = plt.subplots(figsize=(12, 6))
for i, p in enumerate(pid_order): for i, p in enumerate(pid_order):
ax.barh(i, p.duration, left=p.start - first, height=0.6) ax.barh(i, p.duration, left=p.start - first, height=0.6, color=color_map[p.pid])
ax.text(p.start - first, i, f"PID {p.pid} ({p.depth})", va="center") ax.text(p.start - first, i, f"PID {p.pid} ({p.depth})", va="center")
ax.set_yticks(range(len(pid_order))) ax.set_yticks(range(len(pid_order)))
ax.set_yticklabels([f"{p.pid} ({p.depth})" for p in pid_order]) ax.set_yticklabels([f"{p.pid} ({p.depth})" for p in pid_order])
ax.set_xlabel("Seconds from first process start") ax.set_xlabel("Секунд с начала первого процесса")
ax.set_title("Gantt (PID Order)") ax.set_title("Диаграмма процессов (в порядке)")
ax.invert_yaxis() ax.invert_yaxis()
plt.tight_layout() plt.tight_layout()
+28 -16
View File
@@ -12,20 +12,21 @@
#include <sstream> #include <sstream>
#include <cmath> #include <cmath>
constexpr int NIL = -1; constexpr int NIL = -1; // маркер пустого указателя
constexpr int MAX_PROCS = 1024; // Safety buffer for return values constexpr int MAX_PROCS = 1024; // лимит ячеек для результатов
struct Node { struct Node {
int value; int value;
int next; int next; // индекс следующего узла
}; };
struct SharedData { struct SharedData {
int head; int head; // индекс начала списка
int results[MAX_PROCS]; // Section for returning results in SHM int results[MAX_PROCS]; // таблица для возврата индексов от потомков
Node nodes[1]; Node nodes[1]; // массив узлов в памяти
}; };
// получение текущего времени для логов
std::string now() { std::string now() {
timeval tv{}; timeval tv{};
gettimeofday(&tv, nullptr); gettimeofday(&tv, nullptr);
@@ -34,6 +35,7 @@ std::string now() {
return oss.str(); return oss.str();
} }
// логирование старта процесса
void log_start(int head, int depth) { void log_start(int head, int depth) {
std::cout << "PROC_START pid=" << getpid() std::cout << "PROC_START pid=" << getpid()
<< " ppid=" << getppid() << " ppid=" << getppid()
@@ -44,6 +46,7 @@ void log_start(int head, int depth) {
<< '\n' << std::flush; << '\n' << std::flush;
} }
// логирование завершения процесса
void log_end(int head, int depth) { void log_end(int head, int depth) {
std::cout << "PROC_END pid=" << getpid() std::cout << "PROC_END pid=" << getpid()
<< " ppid=" << getppid() << " ppid=" << getppid()
@@ -54,6 +57,7 @@ void log_end(int head, int depth) {
<< '\n' << std::flush; << '\n' << std::flush;
} }
// слияние двух отсортированных списков
int merge_lists(Node* pool, int left_head, int right_head) { int merge_lists(Node* pool, int left_head, int right_head) {
if (left_head == NIL) return right_head; if (left_head == NIL) return right_head;
if (right_head == NIL) return left_head; if (right_head == NIL) return left_head;
@@ -61,6 +65,7 @@ int merge_lists(Node* pool, int left_head, int right_head) {
int res_head = NIL; int res_head = NIL;
int tail = NIL; int tail = NIL;
// лямбда для добавления узла в хвост
auto append = [&](int node_idx) { auto append = [&](int node_idx) {
if (res_head == NIL) { if (res_head == NIL) {
res_head = node_idx; res_head = node_idx;
@@ -87,6 +92,7 @@ int merge_lists(Node* pool, int left_head, int right_head) {
return res_head; return res_head;
} }
// разделение списка пополам (черепаха и заяц)
void split_list(Node* pool, int head, int& left, int& right) { void split_list(Node* pool, int head, int& left, int& right) {
if (head == NIL || pool[head].next == NIL) { if (head == NIL || pool[head].next == NIL) {
left = head; left = head;
@@ -104,9 +110,10 @@ void split_list(Node* pool, int head, int& left, int& right) {
} }
left = head; left = head;
right = pool[slow].next; right = pool[slow].next;
pool[slow].next = NIL; pool[slow].next = NIL; // разрыв связи
} }
// обычная рекурсивная сортировка в одном процессе
int local_list_sort(Node* pool, int head) { int local_list_sort(Node* pool, int head) {
if (head == NIL || pool[head].next == NIL) return head; if (head == NIL || pool[head].next == NIL) return head;
int left, right; int left, right;
@@ -116,7 +123,7 @@ int local_list_sort(Node* pool, int head) {
return merge_lists(pool, left, right); return merge_lists(pool, left, right);
} }
// proc_idx helps each process find its unique slot in data->results // параллельная сортировка через fork
int parallel_list_sort(SharedData* data, int head, int depth, int max_depth, int proc_idx) { int parallel_list_sort(SharedData* data, int head, int depth, int max_depth, int proc_idx) {
log_start(head, depth); log_start(head, depth);
@@ -125,6 +132,7 @@ int parallel_list_sort(SharedData* data, int head, int depth, int max_depth, int
return head; return head;
} }
// если глубина достигнута, сортируем локально
if (depth >= max_depth) { if (depth >= max_depth) {
int result = local_list_sort(data->nodes, head); int result = local_list_sort(data->nodes, head);
log_end(result, depth); log_end(result, depth);
@@ -134,29 +142,29 @@ int parallel_list_sort(SharedData* data, int head, int depth, int max_depth, int
int left_part, right_part; int left_part, right_part;
split_list(data->nodes, head, left_part, right_part); split_list(data->nodes, head, left_part, right_part);
// Calculate unique IDs for children in the results array // индексы для записи результатов в массив shm
int left_child_idx = 2 * proc_idx + 1; int left_child_idx = 2 * proc_idx + 1;
int right_child_idx = 2 * proc_idx + 2; int right_child_idx = 2 * proc_idx + 2;
pid_t pid_l = fork(); pid_t pid_l = fork();
if (pid_l == 0) { if (pid_l == 0) {
int res = parallel_list_sort(data, left_part, depth + 1, max_depth, left_child_idx); int res = parallel_list_sort(data, left_part, depth + 1, max_depth, left_child_idx);
data->results[left_child_idx] = res; // Return result in SHM data->results[left_child_idx] = res; // запись головы в общую память
_exit(0); _exit(0);
} }
pid_t pid_r = fork(); pid_t pid_r = fork();
if (pid_r == 0) { if (pid_r == 0) {
int res = parallel_list_sort(data, right_part, depth + 1, max_depth, right_child_idx); int res = parallel_list_sort(data, right_part, depth + 1, max_depth, right_child_idx);
data->results[right_child_idx] = res; // Return result in SHM data->results[right_child_idx] = res; // запись головы в общую память
_exit(0); _exit(0);
} }
// Synchronize: Parent waits for both children to finish writing to SHM // ждем завершения обоих детей
waitpid(pid_l, nullptr, 0); waitpid(pid_l, nullptr, 0);
waitpid(pid_r, nullptr, 0); waitpid(pid_r, nullptr, 0);
// Read results directly from Shared Memory // читаем головы отсортированных частей из памяти
int sorted_l = data->results[left_child_idx]; int sorted_l = data->results[left_child_idx];
int sorted_r = data->results[right_child_idx]; int sorted_r = data->results[right_child_idx];
@@ -165,31 +173,34 @@ int parallel_list_sort(SharedData* data, int head, int depth, int max_depth, int
return final_head; return final_head;
} }
int main(int argc, char* argv[]) { //main(data count, max recursion level) int main(int argc, char* argv[]) {
int n = 10000; int n = 10000;
int max_depth = 3; int max_depth = 3;
if (argc > 1) n = std::atoi(argv[1]); if (argc > 1) n = std::atoi(argv[1]);
if (argc > 2) max_depth = std::atoi(argv[2]); if (argc > 2) max_depth = std::atoi(argv[2]);
// создание сегмента разделяемой памяти
size_t shm_size = sizeof(SharedData) + sizeof(Node) * (n - 1); size_t shm_size = sizeof(SharedData) + sizeof(Node) * (n - 1);
int shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0666); int shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0666);
SharedData* data = (SharedData*)shmat(shmid, nullptr, 0); SharedData* data = (SharedData*)shmat(shmid, nullptr, 0);
// Initialize return area // зачистка таблицы результатов
for(int i = 0; i < MAX_PROCS; ++i) data->results[i] = NIL; for(int i = 0; i < MAX_PROCS; ++i) data->results[i] = NIL;
data->head = 0; data->head = 0;
std::mt19937 rng(time(0)); std::mt19937 rng(time(0));
std::uniform_int_distribution<int> dist(0, 999); std::uniform_int_distribution<int> dist(0, 999);
// заполнение списка случайными числами
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
data->nodes[i].value = dist(rng); data->nodes[i].value = dist(rng);
data->nodes[i].next = (i == n - 1) ? NIL : i + 1; data->nodes[i].next = (i == n - 1) ? NIL : i + 1;
} }
// Start with proc_idx 0 (the root) // запуск параллельной сортировки (корень — индекс 0)
data->head = parallel_list_sort(data, data->head, 0, max_depth, 0); data->head = parallel_list_sort(data, data->head, 0, max_depth, 0);
// вывод результата
std::cout << "\nSorted list (first 20 elements): "; std::cout << "\nSorted list (first 20 elements): ";
int curr = data->head; int curr = data->head;
for(int i = 0; i < 20 && curr != NIL; ++i) { for(int i = 0; i < 20 && curr != NIL; ++i) {
@@ -198,6 +209,7 @@ int main(int argc, char* argv[]) { //main(data count, max recursion level)
} }
std::cout << std::endl; std::cout << std::endl;
// отсоединение и удаление памяти
shmdt(data); shmdt(data);
shmctl(shmid, IPC_RMID, nullptr); shmctl(shmid, IPC_RMID, nullptr);
return 0; return 0;