From 32767ce7f97305b4c925b8279c5696af1ef1abb1 Mon Sep 17 00:00:00 2001 From: Eladash <18193363+elad335@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:38:12 +0200 Subject: [PATCH] SPU LLVM: Improve runtime SPU compilation preferences --- Utilities/lockless.h | 14 ++++++-- rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 50 ++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/Utilities/lockless.h b/Utilities/lockless.h index f49544ea3d4c..e361434a7fa1 100644 --- a/Utilities/lockless.h +++ b/Utilities/lockless.h @@ -379,8 +379,8 @@ class lf_queue final return m_head != 0; } - template - void push(Args&&... args) + template + bool push(Args&&... args) { auto oldv = m_head.load(); auto item = new lf_queue_item(load(oldv), std::forward(args)...); @@ -393,6 +393,16 @@ class lf_queue final if (!oldv) { // Notify only if queue was empty + notify(true); + } + + return !!oldv; + } + + void notify(bool force = false) + { + if (force || operator bool()) + { utils::bless>(&m_head)[1].notify_one(); } } diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index 7b9cba2347f6..41f80e4e77ae 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -4570,11 +4570,15 @@ struct spu_llvm } u32 worker_index = 0; + u32 notify_compile_count = 0; + std::vector notify_compile(worker_count); m_workers = make_single>("SPUW.", worker_count); auto workers_ptr = m_workers.load(); auto& workers = *workers_ptr; + usz add_count = 65535; + while (thread_ctrl::state() != thread_state::aborting) { for (const auto& pair : registered.pop_all()) @@ -4585,14 +4589,30 @@ struct spu_llvm const auto lock = prof_mutex.init_always([&]{}); // Register new blocks to collect samples - samples.emplace(pair.first, 0); + // If the sample count is the same, prefer the last block that was pushed + samples.emplace(pair.first ? pair.first * 65536 + (add_count-- % 65536) : pair.first * 65536, 0); } if (enqueued.empty()) { + // Send pending notifications + if (notify_compile_count) + { + for (usz i = 0; i < worker_count; i++) + { + if (notify_compile[i]) + { + (workers.begin() + (worker_index % worker_count))->registered.notify(); + } + } + } + // Interrupt profiler thread and put it to sleep static_cast(prof_mutex.reset()); thread_ctrl::wait_on(utils::bless>(®istered)[1], 0); + add_count = 65535; // Reset count + std::fill(notify_compile.begin(), notify_compile.end(), 0); // Reset notification flags + notify_compile_count = 0; continue; } @@ -4620,8 +4640,34 @@ struct spu_llvm // Remove item from the queue enqueued.erase(found_it); + // Prefer using an inactive thread + for (usz i = 0; i < worker_count && !!(workers.begin() + (worker_index % worker_count))->registered; i++) + { + worker_index++; + } + // Push the workload - (workers.begin() + (worker_index++ % worker_count))->registered.push(reinterpret_cast(_old), &func); + const bool notify = (workers.begin() + (worker_index % worker_count))->registered.template push(reinterpret_cast(_old), &func); + + if (notify && !notify_compile[worker_index % worker_count]) + { + notify_compile[worker_index % worker_count] = 1; + notify_compile_cout++; + + if (notify_compile_count == notify_compile.size()) + { + // Notify all + for (usz i = 0; i < worker_count; i++) + { + (workers.begin() + (i % worker_count))->registered.notify(); + } + + std::fill(notify_compile.begin(), notify_compile.end(), 0); // Reset notification flags + notify_compile_count = 0; + } + } + + worker_index++; } static_cast(prof_mutex.init_always([&]{ samples.clear(); }));