Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor PPU LLVM compiling threading #7684

Merged
merged 1 commit into from Mar 4, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
88 changes: 61 additions & 27 deletions rpcs3/Emu/Cell/PPUThread.cpp
Expand Up @@ -1445,12 +1445,6 @@ extern void ppu_initialize(const ppu_module& info)
// Compiler mutex (global)
static shared_mutex jmutex;

// Get jit core allocator instance
const auto jcores = g_fxo->get<jit_core_allocator>();

// Worker threads
std::vector<std::thread> jthreads;

// Global variables to initialize
std::vector<std::pair<std::string, u64>> globals;

Expand All @@ -1460,6 +1454,15 @@ extern void ppu_initialize(const ppu_module& info)
// Difference between function name and current location
const u32 reloc = info.name.empty() ? 0 : info.segs.at(0).addr;

// Info sent to threads
std::vector<std::pair<std::string, ppu_module>> workload;

// Info to load to main JIT instance (true - compiled)
std::vector<std::pair<std::string, bool>> link_workload;

// Sync variable to acquire workloads
atomic_t<u32> work_cv = 0;

while (jit_mod.vars.empty() && fpos < info.funcs.size())
{
// Initialize compiler instance
Expand Down Expand Up @@ -1609,34 +1612,56 @@ extern void ppu_initialize(const ppu_module& info)
globals.emplace_back(fmt::format("__seg%u_%x", i, suffix), info.segs[i].addr);
}

link_workload.emplace_back(obj_name, false);

// Check object file
if (fs::is_file(cache_path + obj_name + ".gz") || fs::is_file(cache_path + obj_name))
{
if (!jit)
{
ppu_log.success("LLVM: Already exists: %s", obj_name);
ppu_log.success("LLVM: Module exists: %s", obj_name);
continue;
}

std::lock_guard lock(jmutex);
jit->add(cache_path + obj_name);

ppu_log.success("LLVM: Loaded module %s", obj_name);
continue;
}

// Adjust information (is_compiled)
link_workload.back().second = true;

// Fill workload list for compilation
workload.emplace_back(std::move(obj_name), std::move(part));

// Update progress dialog
g_progr_ptotal++;
}

// Create worker threads for compilation (TODO: how many threads)
{
u32 thread_count = Emu.GetMaxThreads();

if (workload.size() < thread_count)
{
thread_count = ::size32(workload);
}

// Create worker thread for compilation
jthreads.emplace_back([&jit, obj_name = obj_name, part = std::move(part), &cache_path, jcores]()
struct thread_index_allocator
{
atomic_t<u64> index = 0;
};

named_thread_group threads(fmt::format("PPUW.%u.", ++g_fxo->get<thread_index_allocator>()->index), thread_count, [&]()
{
// Set low priority
thread_ctrl::set_native_priority(-1);

// Allocate "core"
for (u32 i = work_cv++; i < workload.size(); i = work_cv++)
{
std::lock_guard jlock(jcores->sem);
// Keep allocating workload
const auto [obj_name, part] = std::as_const(workload)[i];

// Allocate "core"
std::lock_guard jlock(g_fxo->get<jit_core_allocator>()->sem);

if (!Emu.IsStopped())
{
Expand All @@ -1645,28 +1670,37 @@ extern void ppu_initialize(const ppu_module& info)
// Use another JIT instance
jit_compiler jit2({}, g_cfg.core.llvm_cpu, 0x1);
ppu_initialize2(jit2, part, cache_path, obj_name);

ppu_log.success("LLVM: Compiled module %s", obj_name);
}

g_progr_pdone++;
}
});

threads.join();

if (Emu.IsStopped() || !get_current_cpu_thread())
{
return;
}

if (Emu.IsStopped() || !jit || !fs::is_file(cache_path + obj_name + ".gz"))
std::lock_guard lock(jmutex);

for (auto [obj_name, is_compiled] : link_workload)
{
if (Emu.IsStopped())
{
return;
break;
}

// Proceed with original JIT instance
std::lock_guard lock(jmutex);
jit->add(cache_path + obj_name);

ppu_log.success("LLVM: Compiled module %s", obj_name);
});
}

// Join worker threads
for (auto& thread : jthreads)
{
thread.join();
if (!is_compiled)
{
ppu_log.success("LLVM: Loaded module %s", obj_name);
}
}
}

if (Emu.IsStopped() || !get_current_cpu_thread())
Expand Down