From d2f31b91bfbbd8250e2a512750cf2ee7e9b5642a Mon Sep 17 00:00:00 2001 From: pajjilykk Date: Tue, 28 Apr 2026 15:27:18 +0700 Subject: [PATCH] update 2 main to proper rules --- 2/main.cpp | 247 ++++++++++++++++++++++------------------------------- 1 file changed, 100 insertions(+), 147 deletions(-) diff --git a/2/main.cpp b/2/main.cpp index 648ef8d..52e0b49 100644 --- a/2/main.cpp +++ b/2/main.cpp @@ -1,206 +1,159 @@ -#include -#include -#include #include +#include +#include +#include #include -#include -#include -#include +#include #include #include -#include -#include -#include +#include -// ================= CONFIG ================= -constexpr int kDefaultN = 20000; -constexpr int kPreviewCount = 20; +// ================= СТРУКТУРЫ ================= +constexpr int NIL = -1; -// ================= GLOBAL CONTROL ================= +struct Node { + int value; + int next; +}; + +struct SortResult { + int head; + long long comparisons; +}; + +struct Args { + Node* pool; + int head; + int depth; + SortResult* res_out; +}; + +// ================= ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ================= int active_threads = 0; int max_threads = 4; +pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; -std::mutex log_mutex; - -// ================= TIME ================= -double get_time() { - timeval tv{}; - gettimeofday(&tv, nullptr); - return tv.tv_sec + tv.tv_usec * 1e-6; -} - +// ================= УТИЛИТЫ ================= 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(); } -// ================= SAFE LOGGING ================= -void log_start(int l, int r, int depth) { - std::lock_guard lock(log_mutex); - - std::cout << "START PID=" << getpid() - << " TID=" << pthread_self() +// Формат лога адаптирован под ваш скрипт analyze_log.py +void log_event(const std::string& type, int head, int depth) { + pthread_mutex_lock(&log_mutex); + // Используем head как идентификатор диапазона для парсера + std::cout << type << " TID=" << pthread_self() << " depth=" << depth - << " range=[" << l << "," << r << "] time=" << now() - << '\n'; + << " range=[" << head << "," << head << "]" + << " time=" << now() << std::endl; + pthread_mutex_unlock(&log_mutex); } -void log_end(int l, int r, int depth) { - std::lock_guard lock(log_mutex); - - std::cout << "END PID=" << getpid() - << " TID=" << pthread_self() - << " depth=" << depth - << " range=[" << l << "," << r << "] time=" << now() - << '\n'; -} - -// ================= MERGE ================= -void merge_range(int* arr, int l, int m, int r) { - std::vector tmp; - tmp.reserve(r - l + 1); - - int i = l; - int j = m + 1; - - while (i <= m && j <= r) { - if (arr[i] <= arr[j]) tmp.push_back(arr[i++]); - else tmp.push_back(arr[j++]); +// ================= ЛОГИКА СПИСКА ================= +void split_list(Node* pool, int head, int& left, int& right) { + if (head == NIL || pool[head].next == NIL) { + left = head; right = NIL; return; } - - while (i <= m) tmp.push_back(arr[i++]); - while (j <= r) tmp.push_back(arr[j++]); - - std::copy(tmp.begin(), tmp.end(), arr + l); + int slow = head, 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; } -// ================= LOCAL SORT ================= -void local_sort(int* arr, int l, int r) { - if (l >= r) return; - - int m = l + (r - l) / 2; - local_sort(arr, l, m); - local_sort(arr, m + 1, r); - merge_range(arr, l, m, r); +SortResult merge_lists(Node* pool, int l, int r) { + long long comps = 0; + if (l == NIL) return {r, 0}; + if (r == NIL) return {l, 0}; + int res_head = NIL, tail = NIL; + auto append = [&](int idx) { + if (res_head == NIL) res_head = tail = idx; + else { pool[tail].next = idx; tail = idx; } + }; + while (l != NIL && r != NIL) { + comps++; + if (pool[l].value <= pool[r].value) { int n = pool[l].next; append(l); l = n; } + else { int n = pool[r].next; append(r); r = n; } + } + if (l != NIL) pool[tail].next = l; + if (r != NIL) pool[tail].next = r; + return {res_head, comps}; } -// ================= THREAD ARG ================= -struct Args { - int* arr; - int l; - int r; - int depth; -}; - -void parallel_sort(int* arr, int l, int r, int depth); +// ================= РЕКУРСИЯ ================= +SortResult parallel_list_sort(Node* pool, int head, int depth); void* thread_func(void* arg) { Args* a = (Args*)arg; - parallel_sort(a->arr, a->l, a->r, a->depth); - delete a; + *(a->res_out) = parallel_list_sort(a->pool, a->head, a->depth); return nullptr; } -// ================= PARALLEL SORT ================= -void parallel_sort(int* arr, int l, int r, int depth) { - log_start(l, r, depth); - - if (l >= r) { - log_end(l, r, depth); - return; +SortResult parallel_list_sort(Node* pool, int head, int depth) { + log_event("START", head, depth); + if (head == NIL || pool[head].next == NIL) { + log_event("END", head, depth); + return {head, 0}; } - int m = l + (r - l) / 2; + int left_p, right_p; + split_list(pool, head, left_p, right_p); pthread_t tid; bool spawned = false; + SortResult res_right = {NIL, 0}; - // ===== thread limit control ===== - pthread_mutex_lock(&thread_mutex); + pthread_mutex_lock(&counter_mutex); if (active_threads < max_threads) { active_threads++; spawned = true; } - pthread_mutex_unlock(&thread_mutex); + pthread_mutex_unlock(&counter_mutex); if (spawned) { - Args* args = new Args{arr, m + 1, r, depth + 1}; + Args* args = new Args{pool, right_p, depth + 1, &res_right}; pthread_create(&tid, nullptr, thread_func, args); - parallel_sort(arr, l, m, depth + 1); - + SortResult res_left = parallel_list_sort(pool, left_p, depth + 1); pthread_join(tid, nullptr); - pthread_mutex_lock(&thread_mutex); + pthread_mutex_lock(&counter_mutex); active_threads--; - pthread_mutex_unlock(&thread_mutex); + pthread_mutex_unlock(&counter_mutex); + SortResult m = merge_lists(pool, res_left.head, res_right.head); + delete args; + log_event("END", m.head, depth); + return {m.head, res_left.comparisons + res_right.comparisons + m.comparisons}; } else { - parallel_sort(arr, l, m, depth + 1); - parallel_sort(arr, m + 1, r, depth + 1); - } - - merge_range(arr, l, m, r); - - log_end(l, r, depth); -} - -// ================= UTIL ================= -bool parse_int(const char* s, int& out) { - try { - size_t p; - int v = std::stoi(s, &p); - if (s[p] != '\0' || v < 0) return false; - out = v; - return true; - } catch (...) { - return false; + SortResult res_left = parallel_list_sort(pool, left_p, depth + 1); + SortResult res_r_seq = parallel_list_sort(pool, right_p, depth + 1); + SortResult m = merge_lists(pool, res_left.head, res_r_seq.head); + log_event("END", m.head, depth); + return {m.head, res_left.comparisons + res_r_seq.comparisons + m.comparisons}; } } -// ================= MAIN ================= int main(int argc, char* argv[]) { - int n = kDefaultN; + int n = 10000; + if (argc >= 2) n = std::atoi(argv[1]); + if (argc >= 3) max_threads = std::atoi(argv[2]); - if (argc >= 2 && !parse_int(argv[1], n)) { - std::cerr << "Invalid N\n"; - return 1; + std::vector pool(n); + std::mt19937 rng(time(0)); + for (int i = 0; i < n; i++) { + pool[i].value = rng() % 100000; + pool[i].next = (i == n - 1) ? NIL : i + 1; } - if (argc >= 3 && !parse_int(argv[2], max_threads)) { - std::cerr << "Invalid threads\n"; - return 1; - } - - std::vector arr(n); - - std::mt19937 rng(std::random_device{}()); - std::uniform_int_distribution dist(0, 99999); - - for (int i = 0; i < n; i++) arr[i] = dist(rng); - - std::cout << "Before: "; - for (int i = 0; i < std::min(n, kPreviewCount); i++) - std::cout << arr[i] << " "; - std::cout << "\n\n"; - - double t1 = get_time(); - - parallel_sort(arr.data(), 0, n - 1, 0); - - double t2 = get_time(); - - std::cout << "\nAfter: "; - for (int i = 0; i < std::min(n, kPreviewCount); i++) - std::cout << arr[i] << " "; - std::cout << "\n"; - - std::cout << "\nTime: " << (t2 - t1) << " sec\n"; - + parallel_list_sort(pool.data(), 0, 0); return 0; }