diff --git a/.gitignore b/.gitignore index 4817317..59573a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.xlsx -**/out +**/out/** **/log* **/lab* diff --git a/1/main.cpp b/1/main.cpp index d66a55f..694eaf9 100644 --- a/1/main.cpp +++ b/1/main.cpp @@ -1,187 +1,196 @@ -#include -#include -#include #include -#include -#include -#include +#include #include #include -#include #include +#include #include -#include +#include +#include +#include +#include +#include -namespace { +constexpr int NIL = -1; -constexpr int kDefaultN = 20000; -constexpr int kDefaultMaxDepth = 3; -constexpr int kPreviewCount = 20; +struct Node { + int value; + int next; +}; + +struct SharedData { + int head; + Node nodes[1]; +}; std::string now() { timeval tv{}; gettimeofday(&tv, nullptr); - std::ostringstream oss; oss << tv.tv_sec << "." << std::setfill('0') << std::setw(6) << tv.tv_usec; return oss.str(); } -void log_start(int l, int r, int depth) { +void log_start(int head, int depth) { std::cout << "PROC_START pid=" << getpid() << " ppid=" << getppid() << " depth=" << depth - << " l=" << l - << " r=" << r + << " l=" << head + << " r=0" << " ts=" << now() << '\n' << std::flush; } -void log_end(int l, int r, int depth) { +void log_end(int head, int depth) { std::cout << "PROC_END pid=" << getpid() << " ppid=" << getppid() << " depth=" << depth - << " l=" << l - << " r=" << r + << " l=" << head + << " r=0" << " ts=" << now() << '\n' << std::flush; } -void merge_range(int* arr, int l, int m, int r) { - std::vector temp; - temp.reserve(r - l + 1); +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; - int i = l; - int j = m + 1; + int res_head = NIL; + int tail = NIL; - while (i <= m && j <= r) { - if (arr[i] <= arr[j]) { - temp.push_back(arr[i++]); + auto append = [&](int node_idx) { + if (res_head == NIL) { + res_head = node_idx; + tail = node_idx; } else { - temp.push_back(arr[j++]); + pool[tail].next = node_idx; + tail = node_idx; + } + }; + + while (left_head != NIL && right_head != NIL) { + if (pool[left_head].value <= pool[right_head].value) { + int next = pool[left_head].next; + append(left_head); + left_head = next; + } else { + int next = pool[right_head].next; + append(right_head); + right_head = next; } } - - while (i <= m) temp.push_back(arr[i++]); - while (j <= r) temp.push_back(arr[j++]); - - std::copy(temp.begin(), temp.end(), arr + l); + if (left_head != NIL) pool[tail].next = left_head; + if (right_head != NIL) pool[tail].next = right_head; + return res_head; } -void local_sort(int* arr, int l, int r) { - if (l >= r) return; - - const int m = l + (r - l) / 2; - local_sort(arr, l, m); - local_sort(arr, m + 1, r); - merge_range(arr, l, m, r); -} - -void parallel_sort(int* arr, int l, int r, int depth, int max_depth) { - log_start(l, r, depth); - - if (l >= r) { - log_end(l, r, depth); +void split_list(Node* pool, int head, int& left, int& right) { + if (head == NIL || pool[head].next == NIL) { + left = head; + right = NIL; return; } + int slow = head; + int fast = pool[head].next; + while (fast != NIL) { + fast = pool[fast].next; + if (fast != NIL) { + slow = pool[slow].next; + fast = pool[fast].next; + } + } + left = head; + right = pool[slow].next; + pool[slow].next = NIL; +} + +int local_list_sort(Node* pool, int head) { + if (head == NIL || pool[head].next == NIL) return head; + int left, right; + split_list(pool, head, left, right); + left = local_list_sort(pool, left); + right = local_list_sort(pool, right); + return merge_lists(pool, left, right); +} + +int parallel_list_sort(Node* pool, int head, int depth, int max_depth) { + log_start(head, depth); + + if (head == NIL || pool[head].next == NIL) { + log_end(head, depth); + return head; + } - const int m = l + (r - l) / 2; if (depth >= max_depth) { - local_sort(arr, l, r); - log_end(l, r, depth); - return; + int result = local_list_sort(pool, head); + log_end(result, depth); + return result; } - pid_t left = fork(); - if (left == 0) { - parallel_sort(arr, l, m, depth + 1, max_depth); - _exit(EXIT_SUCCESS); + int left_part, right_part; + split_list(pool, head, left_part, right_part); + + int pipe_l[2], pipe_r[2]; + pipe(pipe_l); + pipe(pipe_r); + + // Левый потомок + pid_t pid_l = fork(); + if (pid_l == 0) { + close(pipe_l[0]); close(pipe_r[0]); close(pipe_r[1]); + int res = parallel_list_sort(pool, left_part, depth + 1, max_depth); + write(pipe_l[1], &res, sizeof(int)); + close(pipe_l[1]); + _exit(0); } - if (left < 0) { - std::perror("fork left"); - local_sort(arr, l, m); + // Правый потомок + pid_t pid_r = fork(); + if (pid_r == 0) { + close(pipe_r[0]); close(pipe_l[0]); close(pipe_l[1]); + int res = parallel_list_sort(pool, right_part, depth + 1, max_depth); + write(pipe_r[1], &res, sizeof(int)); + close(pipe_r[1]); + _exit(0); } - pid_t right = fork(); - if (right == 0) { - parallel_sort(arr, m + 1, r, depth + 1, max_depth); - _exit(EXIT_SUCCESS); - } + // Родитель ждет обоих + int sorted_l, sorted_r; + close(pipe_l[1]); close(pipe_r[1]); - if (right < 0) { - std::perror("fork right"); - local_sort(arr, m + 1, r); - } + waitpid(pid_l, nullptr, 0); + read(pipe_l[0], &sorted_l, sizeof(int)); - int left_status = 0; - if (left > 0 && waitpid(left, &left_status, 0) < 0) { - std::perror("waitpid left"); - local_sort(arr, l, m); - } else if (left > 0 && (!WIFEXITED(left_status) || WEXITSTATUS(left_status) != 0)) { - local_sort(arr, l, m); - } + waitpid(pid_r, nullptr, 0); + read(pipe_r[0], &sorted_r, sizeof(int)); - int right_status = 0; - if (right > 0 && waitpid(right, &right_status, 0) < 0) { - std::perror("waitpid right"); - local_sort(arr, m + 1, r); - } else if (right > 0 && (!WIFEXITED(right_status) || WEXITSTATUS(right_status) != 0)) { - local_sort(arr, m + 1, r); - } + close(pipe_l[0]); close(pipe_r[0]); - merge_range(arr, l, m, r); - log_end(l, r, depth); + int final_head = merge_lists(pool, sorted_l, sorted_r); + log_end(final_head, depth); + return final_head; } -bool parse_positive_int(const char* value, int& out) { - try { - size_t consumed = 0; - const int parsed = std::stoi(value, &consumed); - if (value[consumed] != '\0') return false; - if (parsed <= 0) return false; - out = parsed; - return true; - } catch (...) { return false; } -} - -} // namespace - int main(int argc, char* argv[]) { - int n = kDefaultN; - int max_depth = kDefaultMaxDepth; + int n = 1000; + int max_depth = 3; + if (argc > 1) n = std::atoi(argv[1]); + if (argc > 2) max_depth = std::atoi(argv[2]); - if (argc >= 2 && !parse_positive_int(argv[1], n)) { - std::cerr << "Invalid array size: " << argv[1] << '\n'; - return EXIT_FAILURE; - } - if (argc >= 3 && !parse_positive_int(argv[2], max_depth)) { - std::cerr << "Invalid max depth: " << argv[2] << '\n'; - return EXIT_FAILURE; + size_t shm_size = sizeof(int) + sizeof(Node) * n; + int shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0666); + SharedData* data = (SharedData*)shmat(shmid, nullptr, 0); + + std::mt19937 rng(time(0)); + std::uniform_int_distribution dist(0, 9999); + for (int i = 0; i < n; ++i) { + data->nodes[i].value = dist(rng); + data->nodes[i].next = (i == n - 1) ? NIL : i + 1; } - const size_t shm_size = static_cast(n) * sizeof(int); - const int shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0600); - if (shmid < 0) { - std::perror("shmget"); - return EXIT_FAILURE; - } + data->head = parallel_list_sort(data->nodes, data->head, 0, max_depth); - int* arr = static_cast(shmat(shmid, nullptr, 0)); - if (arr == reinterpret_cast(-1)) { - std::perror("shmat"); - shmctl(shmid, IPC_RMID, nullptr); - return EXIT_FAILURE; - } - - std::mt19937 rng(std::random_device{}()); - std::uniform_int_distribution dist(0, 99999); - for (int i = 0; i < n; ++i) arr[i] = dist(rng); - - parallel_sort(arr, 0, n - 1, 0, max_depth); - - if (shmdt(arr) < 0) std::perror("shmdt"); - if (shmctl(shmid, IPC_RMID, nullptr) < 0) std::perror("shmctl IPC_RMID"); - - return EXIT_SUCCESS; + shmdt(data); + shmctl(shmid, IPC_RMID, nullptr); + return 0; } diff --git a/1/out/gantt.png b/1/out/gantt.png deleted file mode 100644 index 0430527..0000000 Binary files a/1/out/gantt.png and /dev/null differ diff --git a/1/out/gantt_pid.png b/1/out/gantt_pid.png index 8733d39..e761fbb 100644 Binary files a/1/out/gantt_pid.png and b/1/out/gantt_pid.png differ diff --git a/1/out/gantt_tree.png b/1/out/gantt_tree.png index 31af6bc..cdca79a 100644 Binary files a/1/out/gantt_tree.png and b/1/out/gantt_tree.png differ diff --git a/1/out/processes.md b/1/out/processes.md index e6bcdb7..0a69579 100644 --- a/1/out/processes.md +++ b/1/out/processes.md @@ -1,17 +1,17 @@ | PID | PPID | Depth | Start | End | Offset | Duration | |---|---|---|---|---|---|---| -| 45686 | 45683 | 0 | 1777075170.175506 | 1777075170.185554 | 0.000000 | 0.010048 | -| 45687 | 45686 | 1 | 1777075170.176607 | 1777075170.184457 | 0.001101 | 0.007850 | -| 45689 | 45687 | 2 | 1777075170.177348 | 1777075170.182180 | 0.001842 | 0.004832 | -| 45693 | 45689 | 3 | 1777075170.178106 | 1777075170.180091 | 0.002600 | 0.001985 | -| 45696 | 45689 | 3 | 1777075170.178728 | 1777075170.180323 | 0.003222 | 0.001595 | -| 45691 | 45687 | 2 | 1777075170.177532 | 1777075170.183675 | 0.002026 | 0.006143 | -| 45695 | 45691 | 3 | 1777075170.178382 | 1777075170.182874 | 0.002876 | 0.004492 | -| 45698 | 45691 | 3 | 1777075170.178693 | 1777075170.180896 | 0.003187 | 0.002203 | -| 45688 | 45686 | 1 | 1777075170.176646 | 1777075170.184045 | 0.001140 | 0.007399 | -| 45690 | 45688 | 2 | 1777075170.177346 | 1777075170.182832 | 0.001840 | 0.005486 | -| 45694 | 45690 | 3 | 1777075170.178801 | 1777075170.180342 | 0.003295 | 0.001541 | -| 45697 | 45690 | 3 | 1777075170.180099 | 1777075170.182005 | 0.004593 | 0.001906 | -| 45692 | 45688 | 2 | 1777075170.178014 | 1777075170.183226 | 0.002508 | 0.005212 | -| 45699 | 45692 | 3 | 1777075170.178864 | 1777075170.180396 | 0.003358 | 0.001532 | -| 45700 | 45692 | 3 | 1777075170.181111 | 1777075170.182464 | 0.005605 | 0.001353 | +| 27445 | 27444 | 0 | 1777360735.363420 | 1777360735.365566 | 0.000000 | 0.002146 | +| 27446 | 27445 | 1 | 1777360735.363734 | 1777360735.365203 | 0.000314 | 0.001469 | +| 27448 | 27446 | 2 | 1777360735.364001 | 1777360735.364799 | 0.000581 | 0.000798 | +| 27452 | 27448 | 3 | 1777360735.364270 | 1777360735.364333 | 0.000850 | 0.000063 | +| 27454 | 27448 | 3 | 1777360735.364405 | 1777360735.364467 | 0.000985 | 0.000062 | +| 27450 | 27446 | 2 | 1777360735.364143 | 1777360735.365022 | 0.000723 | 0.000879 | +| 27458 | 27450 | 3 | 1777360735.364584 | 1777360735.364655 | 0.001164 | 0.000071 | +| 27456 | 27450 | 3 | 1777360735.364653 | 1777360735.364767 | 0.001233 | 0.000114 | +| 27447 | 27445 | 1 | 1777360735.363775 | 1777360735.365355 | 0.000355 | 0.001580 | +| 27449 | 27447 | 2 | 1777360735.364026 | 1777360735.364811 | 0.000606 | 0.000785 | +| 27453 | 27449 | 3 | 1777360735.364323 | 1777360735.364385 | 0.000903 | 0.000062 | +| 27455 | 27449 | 3 | 1777360735.364502 | 1777360735.364563 | 0.001082 | 0.000061 | +| 27451 | 27447 | 2 | 1777360735.364192 | 1777360735.365179 | 0.000772 | 0.000987 | +| 27457 | 27451 | 3 | 1777360735.364683 | 1777360735.364743 | 0.001263 | 0.000060 | +| 27459 | 27451 | 3 | 1777360735.364906 | 1777360735.364965 | 0.001486 | 0.000059 |