mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-20 22:05:12 +00:00
Implement named_thread_group
This commit is contained in:
parent
eb140c52a4
commit
f72971f19f
4 changed files with 150 additions and 76 deletions
|
|
@ -394,11 +394,6 @@ void spu_cache::initialize()
|
|||
atomic_t<std::size_t> fnext{};
|
||||
atomic_t<u8> fail_flag{0};
|
||||
|
||||
// Initialize compiler instances for parallel compilation
|
||||
u32 max_threads = static_cast<u32>(g_cfg.core.llvm_threads);
|
||||
u32 thread_count = max_threads > 0 ? std::min(max_threads, std::thread::hardware_concurrency()) : std::thread::hardware_concurrency();
|
||||
std::vector<std::unique_ptr<spu_recompiler_base>> compilers{thread_count};
|
||||
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::fast || g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
if (auto compiler = spu_recompiler_base::make_llvm_recompiler(11))
|
||||
|
|
@ -421,26 +416,7 @@ void spu_cache::initialize()
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& compiler : compilers)
|
||||
{
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_asmjit_recompiler();
|
||||
}
|
||||
else if (g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_llvm_recompiler();
|
||||
}
|
||||
else
|
||||
{
|
||||
compilers.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
compiler->init();
|
||||
}
|
||||
|
||||
if (!compilers.empty() && !func_list.empty())
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit || g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
// Initialize progress dialog (wait for previous progress done)
|
||||
while (g_progr_ptotal)
|
||||
|
|
@ -452,10 +428,25 @@ void spu_cache::initialize()
|
|||
g_progr_ptotal += func_list.size();
|
||||
}
|
||||
|
||||
std::deque<named_thread<std::function<void()>>> thread_queue;
|
||||
|
||||
for (std::size_t i = 0; i < compilers.size(); i++) thread_queue.emplace_back("Worker " + std::to_string(i), [&, compiler = compilers[i].get()]()
|
||||
named_thread_group workers("SPU Worker ", Emu.GetMaxThreads(), [&]() -> uint
|
||||
{
|
||||
// Initialize compiler instances for parallel compilation
|
||||
std::unique_ptr<spu_recompiler_base> compiler;
|
||||
|
||||
if (g_cfg.core.spu_decoder == spu_decoder_type::asmjit)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_asmjit_recompiler();
|
||||
}
|
||||
else if (g_cfg.core.spu_decoder == spu_decoder_type::llvm)
|
||||
{
|
||||
compiler = spu_recompiler_base::make_llvm_recompiler();
|
||||
}
|
||||
|
||||
compiler->init();
|
||||
|
||||
// How much every thread compiled
|
||||
uint result = 0;
|
||||
|
||||
// Fake LS
|
||||
std::vector<be_t<u32>> ls(0x10000);
|
||||
|
||||
|
|
@ -497,13 +488,17 @@ void spu_cache::initialize()
|
|||
std::memset(ls.data() + start / 4, 0, 4 * (size0 - 1));
|
||||
|
||||
g_progr_pdone++;
|
||||
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
// Join all threads
|
||||
while (!thread_queue.empty())
|
||||
// Join (implicitly) and print individual results
|
||||
for (u32 i = 0; i < workers.size(); i++)
|
||||
{
|
||||
thread_queue.pop_front();
|
||||
spu_log.notice("SPU Runtime: Worker %u built %u programs.", i + 1, workers[i]);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
|
|
@ -518,7 +513,7 @@ void spu_cache::initialize()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!compilers.empty() && !func_list.empty())
|
||||
if ((g_cfg.core.spu_decoder == spu_decoder_type::asmjit || g_cfg.core.spu_decoder == spu_decoder_type::llvm) && !func_list.empty())
|
||||
{
|
||||
spu_log.success("SPU Runtime: Built %u functions.", func_list.size());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -925,9 +925,6 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
std::vector<std::pair<std::string, u64>> file_queue;
|
||||
file_queue.reserve(2000);
|
||||
|
||||
std::queue<named_thread<std::function<void()>>> thread_queue;
|
||||
const uint max_threads = std::thread::hardware_concurrency();
|
||||
|
||||
// Initialize progress dialog
|
||||
g_progr = "Scanning directories for SPRX libraries...";
|
||||
|
||||
|
|
@ -975,57 +972,46 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
|
||||
g_progr = "Compiling PPU modules";
|
||||
|
||||
atomic_t<u32> worker_count = 0;
|
||||
atomic_t<std::size_t> fnext = 0;
|
||||
|
||||
for (std::size_t i = 0; i < file_queue.size(); i++)
|
||||
named_thread_group workers("SPRX Worker ", GetMaxThreads(), [&]
|
||||
{
|
||||
const auto& path = file_queue[i].first;
|
||||
|
||||
sys_log.notice("Trying to load SPRX: %s", path);
|
||||
|
||||
// Load MSELF or SPRX
|
||||
fs::file src{path};
|
||||
|
||||
if (file_queue[i].second == 0)
|
||||
for (std::size_t func_i = fnext++; func_i < file_queue.size(); func_i = fnext++)
|
||||
{
|
||||
// Some files may fail to decrypt due to the lack of klic
|
||||
src = decrypt_self(std::move(src));
|
||||
}
|
||||
const auto& path = std::as_const(file_queue)[func_i].first;
|
||||
|
||||
const ppu_prx_object obj = src;
|
||||
sys_log.notice("Trying to load SPRX: %s", path);
|
||||
|
||||
if (obj == elf_error::ok)
|
||||
{
|
||||
if (auto prx = ppu_load_prx(obj, path))
|
||||
// Load MSELF or SPRX
|
||||
fs::file src{path};
|
||||
|
||||
if (file_queue[func_i].second == 0)
|
||||
{
|
||||
worker_count++;
|
||||
|
||||
while (worker_count > max_threads)
|
||||
{
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
|
||||
thread_queue.emplace("Worker " + std::to_string(thread_queue.size()), [_prx = std::move(prx), &worker_count]
|
||||
{
|
||||
ppu_initialize(*_prx);
|
||||
ppu_unload_prx(*_prx);
|
||||
g_progr_fdone++;
|
||||
worker_count--;
|
||||
});
|
||||
|
||||
continue;
|
||||
// Some files may fail to decrypt due to the lack of klic
|
||||
src = decrypt_self(std::move(src));
|
||||
}
|
||||
}
|
||||
|
||||
sys_log.error("Failed to load SPRX '%s' (%s)", path, obj.get_error());
|
||||
g_progr_fdone++;
|
||||
}
|
||||
const ppu_prx_object obj = src;
|
||||
|
||||
if (obj == elf_error::ok)
|
||||
{
|
||||
if (auto prx = ppu_load_prx(obj, path))
|
||||
{
|
||||
ppu_initialize(*prx);
|
||||
ppu_unload_prx(*prx);
|
||||
g_progr_fdone++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sys_log.error("Failed to load SPRX '%s' (%s)", path, obj.get_error());
|
||||
g_progr_fdone++;
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
// Join every thread
|
||||
while (!thread_queue.empty())
|
||||
{
|
||||
thread_queue.pop();
|
||||
}
|
||||
workers.join();
|
||||
|
||||
// Exit "process"
|
||||
Emu.CallAfter([]
|
||||
|
|
@ -1719,6 +1705,13 @@ std::string Emulator::GetFormattedTitle(double fps) const
|
|||
return rpcs3::get_formatted_title(title_data);
|
||||
}
|
||||
|
||||
u32 Emulator::GetMaxThreads() const
|
||||
{
|
||||
u32 max_threads = static_cast<u32>(g_cfg.core.llvm_threads);
|
||||
u32 thread_count = max_threads > 0 ? std::min(max_threads, std::thread::hardware_concurrency()) : std::thread::hardware_concurrency();
|
||||
return thread_count;
|
||||
}
|
||||
|
||||
s32 error_code::error_report(const fmt_type_info* sup, u64 arg, const fmt_type_info* sup2, u64 arg2)
|
||||
{
|
||||
static thread_local std::unordered_map<std::string, std::size_t> g_tls_error_stats;
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ public:
|
|||
void SetHasGui(bool has_gui) { m_has_gui = has_gui; }
|
||||
|
||||
std::string GetFormattedTitle(double fps) const;
|
||||
|
||||
u32 GetMaxThreads() const;
|
||||
};
|
||||
|
||||
extern Emulator Emu;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue