final cleanup 1
This commit is contained in:
+28
-16
@@ -12,20 +12,21 @@
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
constexpr int NIL = -1;
|
||||
constexpr int MAX_PROCS = 1024; // Safety buffer for return values
|
||||
constexpr int NIL = -1; // маркер пустого указателя
|
||||
constexpr int MAX_PROCS = 1024; // лимит ячеек для результатов
|
||||
|
||||
struct Node {
|
||||
int value;
|
||||
int next;
|
||||
int next; // индекс следующего узла
|
||||
};
|
||||
|
||||
struct SharedData {
|
||||
int head;
|
||||
int results[MAX_PROCS]; // Section for returning results in SHM
|
||||
Node nodes[1];
|
||||
int head; // индекс начала списка
|
||||
int results[MAX_PROCS]; // таблица для возврата индексов от потомков
|
||||
Node nodes[1]; // массив узлов в памяти
|
||||
};
|
||||
|
||||
// получение текущего времени для логов
|
||||
std::string now() {
|
||||
timeval tv{};
|
||||
gettimeofday(&tv, nullptr);
|
||||
@@ -34,6 +35,7 @@ std::string now() {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// логирование старта процесса
|
||||
void log_start(int head, int depth) {
|
||||
std::cout << "PROC_START pid=" << getpid()
|
||||
<< " ppid=" << getppid()
|
||||
@@ -44,6 +46,7 @@ void log_start(int head, int depth) {
|
||||
<< '\n' << std::flush;
|
||||
}
|
||||
|
||||
// логирование завершения процесса
|
||||
void log_end(int head, int depth) {
|
||||
std::cout << "PROC_END pid=" << getpid()
|
||||
<< " ppid=" << getppid()
|
||||
@@ -54,6 +57,7 @@ void log_end(int head, int depth) {
|
||||
<< '\n' << std::flush;
|
||||
}
|
||||
|
||||
// слияние двух отсортированных списков
|
||||
int merge_lists(Node* pool, int left_head, int right_head) {
|
||||
if (left_head == NIL) return right_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 tail = NIL;
|
||||
|
||||
// лямбда для добавления узла в хвост
|
||||
auto append = [&](int node_idx) {
|
||||
if (res_head == NIL) {
|
||||
res_head = node_idx;
|
||||
@@ -87,6 +92,7 @@ int merge_lists(Node* pool, int left_head, int right_head) {
|
||||
return res_head;
|
||||
}
|
||||
|
||||
// разделение списка пополам (черепаха и заяц)
|
||||
void split_list(Node* pool, int head, int& left, int& right) {
|
||||
if (head == NIL || pool[head].next == NIL) {
|
||||
left = head;
|
||||
@@ -104,9 +110,10 @@ void split_list(Node* pool, int head, int& left, int& right) {
|
||||
}
|
||||
left = head;
|
||||
right = pool[slow].next;
|
||||
pool[slow].next = NIL;
|
||||
pool[slow].next = NIL; // разрыв связи
|
||||
}
|
||||
|
||||
// обычная рекурсивная сортировка в одном процессе
|
||||
int local_list_sort(Node* pool, int head) {
|
||||
if (head == NIL || pool[head].next == NIL) return head;
|
||||
int left, right;
|
||||
@@ -116,7 +123,7 @@ int local_list_sort(Node* pool, int head) {
|
||||
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) {
|
||||
log_start(head, depth);
|
||||
|
||||
@@ -125,6 +132,7 @@ int parallel_list_sort(SharedData* data, int head, int depth, int max_depth, int
|
||||
return head;
|
||||
}
|
||||
|
||||
// если глубина достигнута, сортируем локально
|
||||
if (depth >= max_depth) {
|
||||
int result = local_list_sort(data->nodes, head);
|
||||
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;
|
||||
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 right_child_idx = 2 * proc_idx + 2;
|
||||
|
||||
pid_t pid_l = fork();
|
||||
if (pid_l == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
pid_t pid_r = fork();
|
||||
if (pid_r == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Synchronize: Parent waits for both children to finish writing to SHM
|
||||
// ждем завершения обоих детей
|
||||
waitpid(pid_l, nullptr, 0);
|
||||
waitpid(pid_r, nullptr, 0);
|
||||
|
||||
// Read results directly from Shared Memory
|
||||
// читаем головы отсортированных частей из памяти
|
||||
int sorted_l = data->results[left_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;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) { //main(data count, max recursion level)
|
||||
int main(int argc, char* argv[]) {
|
||||
int n = 10000;
|
||||
int max_depth = 3;
|
||||
if (argc > 1) n = std::atoi(argv[1]);
|
||||
if (argc > 2) max_depth = std::atoi(argv[2]);
|
||||
|
||||
// создание сегмента разделяемой памяти
|
||||
size_t shm_size = sizeof(SharedData) + sizeof(Node) * (n - 1);
|
||||
int shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0666);
|
||||
SharedData* data = (SharedData*)shmat(shmid, nullptr, 0);
|
||||
|
||||
// Initialize return area
|
||||
// зачистка таблицы результатов
|
||||
for(int i = 0; i < MAX_PROCS; ++i) data->results[i] = NIL;
|
||||
|
||||
data->head = 0;
|
||||
std::mt19937 rng(time(0));
|
||||
std::uniform_int_distribution<int> dist(0, 999);
|
||||
|
||||
// заполнение списка случайными числами
|
||||
for (int i = 0; i < n; ++i) {
|
||||
data->nodes[i].value = dist(rng);
|
||||
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);
|
||||
|
||||
// вывод результата
|
||||
std::cout << "\nSorted list (first 20 elements): ";
|
||||
int curr = data->head;
|
||||
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;
|
||||
|
||||
// отсоединение и удаление памяти
|
||||
shmdt(data);
|
||||
shmctl(shmid, IPC_RMID, nullptr);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user