1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

Scheduler overhaul

This commit is contained in:
xddxd 2021-03-17 18:28:03 +02:00 committed by Ivan
parent a7acb84b8b
commit 9d895e6b15
12 changed files with 101 additions and 47 deletions

View File

@ -2709,9 +2709,18 @@ u64 thread_ctrl::get_affinity_mask(thread_class group)
break;
case 16:
// 1700, 1800, 2700, TR 1900X family
ppu_mask = 0b1111111100000000;
spu_mask = ppu_mask;
rsx_mask = 0b0000000000111100;
if (g_cfg.core.thread_scheduler == thread_scheduler_mode::alt)
{
ppu_mask = 0b0010000010000000;
spu_mask = 0b0000101010101010;
rsx_mask = 0b1000000000000000;
}
else
{
ppu_mask = 0b1111111100000000;
spu_mask = ppu_mask;
rsx_mask = 0b0000000000111100;
}
break;
case 12:
// 1600, 2600 family, Assign threads 3-12
@ -2739,16 +2748,36 @@ u64 thread_ctrl::get_affinity_mask(thread_class group)
spu_mask = 0b000000111111000000000000;
rsx_mask = 0b000000000000111111000000;
break;
default:
if (thread_count >= 16)
case 16:
// 5800X
if (g_cfg.core.thread_scheduler == thread_scheduler_mode::alt)
{
ppu_mask = 0b0000000011110000;
spu_mask = 0b1111111100000000;
rsx_mask = 0b0000000000001111;
}
else
{
// Verified by more than one windows user on 16-thread CPU
ppu_mask = spu_mask = rsx_mask = (0b10101010101010101010101010101010 & all_cores_mask);
}
case 12:
// 5600X
if (g_cfg.core.thread_scheduler == thread_scheduler_mode::alt)
{
ppu_mask = 0b000000001100;
spu_mask = 0b111111110000;
rsx_mask = 0b000000000011;
}
else
{
ppu_mask = spu_mask = rsx_mask = all_cores_mask;
}
default:
if (thread_count > 24)
{
ppu_mask = spu_mask = rsx_mask = (0b10101010101010101010101010101010 & all_cores_mask);
}
break;
}
break;
@ -2774,23 +2803,8 @@ u64 thread_ctrl::get_affinity_mask(thread_class group)
}
case native_core_arrangement::intel_ht:
{
/* This has been disabled as it seems to degrade performance instead of improving it.
if (thread_count <= 4)
{
//i3 or worse
switch (group)
{
case thread_class::rsx:
case thread_class::ppu:
return (0b0101 & all_cores_mask);
case thread_class::spu:
return (0b1010 & all_cores_mask);
case thread_class::general:
return all_cores_mask;
}
}
*/
if (thread_count >= 12 && g_cfg.core.thread_scheduler == thread_scheduler_mode::alt)
return (0b10101010101010101010101010101010 & all_cores_mask); // Potentially improves performance by mimicking HT off
return all_cores_mask;
}
}

View File

@ -405,7 +405,7 @@ void cpu_thread::operator()()
{
g_tls_this_thread = this;
if (g_cfg.core.thread_scheduler_enabled)
if (g_cfg.core.thread_scheduler != thread_scheduler_mode::os)
{
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(id_type() == 1 ? thread_class::ppu : thread_class::spu));
}

View File

@ -29,7 +29,7 @@ namespace rsx
m_thread_id = std::this_thread::get_id();
if (g_cfg.core.thread_scheduler_enabled)
if (g_cfg.core.thread_scheduler != thread_scheduler_mode::os)
{
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(thread_class::rsx));
}

View File

@ -639,7 +639,7 @@ namespace rsx
// Raise priority above other threads
thread_ctrl::scoped_priority high_prio(+1);
if (g_cfg.core.thread_scheduler_enabled)
if (g_cfg.core.thread_scheduler != thread_scheduler_mode::os)
{
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(thread_class::rsx));
}

View File

@ -17,13 +17,6 @@ struct cfg_root : cfg::node
bool has_rtm() const;
public:
static constexpr bool thread_scheduler_enabled_def =
#ifdef _WIN32
true;
#else
false;
#endif
node_core(cfg::node* _this) : cfg::node(_this, "Core") {}
cfg::_enum<ppu_decoder_type> ppu_decoder{ this, "PPU Decoder", ppu_decoder_type::llvm };
@ -33,7 +26,7 @@ struct cfg_root : cfg::node
cfg::string llvm_cpu{ this, "Use LLVM CPU" };
cfg::_int<0, INT32_MAX> llvm_threads{ this, "Max LLVM Compile Threads", 0 };
cfg::_bool ppu_llvm_greedy_mode{ this, "PPU LLVM Greedy Mode", false, false };
cfg::_bool thread_scheduler_enabled{ this, "Enable thread scheduler", thread_scheduler_enabled_def };
cfg::_enum<thread_scheduler_mode> thread_scheduler{this, "Thread Scheduler Mode", thread_scheduler_mode::os};
cfg::_bool set_daz_and_ftz{ this, "Set DAZ and FTZ", false };
cfg::_enum<spu_decoder_type> spu_decoder{ this, "SPU Decoder", spu_decoder_type::llvm };
cfg::_bool lower_spu_priority{ this, "Lower SPU thread priority" };

View File

@ -436,3 +436,19 @@ void fmt_class_string<vk_gpu_scheduler_mode>::format(std::string& out, u64 arg)
return unknown;
});
}
template <>
void fmt_class_string<thread_scheduler_mode>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](thread_scheduler_mode value)
{
switch (value)
{
case thread_scheduler_mode::old: return "RPCS3 Scheduler";
case thread_scheduler_mode::alt: return "RPCS3 Alternative Scheduler";
case thread_scheduler_mode::os: return "Operating System";
}
return unknown;
});
}

View File

@ -201,3 +201,10 @@ enum class vk_gpu_scheduler_mode
host,
device
};
enum class thread_scheduler_mode
{
os,
old,
alt
};

View File

@ -831,6 +831,14 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
case spu_block_size_type::giga: return tr("Giga", "SPU block size");
}
break;
case emu_settings_type::ThreadSchedulerMode:
switch (static_cast<thread_scheduler_mode>(index))
{
case thread_scheduler_mode::old: return tr("RPCS3 Scheduler", "Thread Scheduler Mode");
case thread_scheduler_mode::alt: return tr("RPCS3 Alternative Scheduler", "Thread Scheduler Mode");
case thread_scheduler_mode::os: return tr("Operating System", "Thread Scheduler Mode");
}
break;
case emu_settings_type::EnableTSX:
switch (static_cast<tsx_usage>(index))
{

View File

@ -11,7 +11,7 @@ enum class emu_settings_type
PPUDecoder,
SPUDecoder,
HookStaticFuncs,
EnableThreadScheduler,
ThreadSchedulerMode,
LowerSPUThreadPrio,
SPULoopDetection,
PreferredSPUThreads,
@ -162,7 +162,7 @@ static const QMap<emu_settings_type, cfg_location> settings_location =
{ emu_settings_type::PPUDecoder, { "Core", "PPU Decoder"}},
{ emu_settings_type::SPUDecoder, { "Core", "SPU Decoder"}},
{ emu_settings_type::HookStaticFuncs, { "Core", "Hook static functions"}},
{ emu_settings_type::EnableThreadScheduler, { "Core", "Enable thread scheduler"}},
{ emu_settings_type::ThreadSchedulerMode, { "Core", "Thread Scheduler Mode"}},
{ emu_settings_type::LowerSPUThreadPrio, { "Core", "Lower SPU thread priority"}},
{ emu_settings_type::SPULoopDetection, { "Core", "SPU loop detection"}},
{ emu_settings_type::PreferredSPUThreads, { "Core", "Preferred SPU Threads"}},

View File

@ -193,9 +193,6 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceCheckBox(ui->spuCache, emu_settings_type::SPUCache);
SubscribeTooltip(ui->spuCache, tooltips.settings.spu_cache);
m_emu_settings->EnhanceCheckBox(ui->enableScheduler, emu_settings_type::EnableThreadScheduler);
SubscribeTooltip(ui->enableScheduler, tooltips.settings.enable_thread_scheduler);
m_emu_settings->EnhanceCheckBox(ui->lowerSPUThrPrio, emu_settings_type::LowerSPUThreadPrio);
SubscribeTooltip(ui->lowerSPUThrPrio, tooltips.settings.lower_spu_thread_priority);
@ -210,6 +207,14 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceComboBox(ui->spuBlockSize, emu_settings_type::SPUBlockSize);
SubscribeTooltip(ui->gb_spuBlockSize, tooltips.settings.spu_block_size);
m_emu_settings->EnhanceComboBox(ui->threadsched, emu_settings_type::ThreadSchedulerMode);
SubscribeTooltip(ui->gb_threadsched, tooltips.settings.enable_thread_scheduler);
if (u32 min_thread_count = 12; utils::get_thread_count() < min_thread_count)
{
ui->gb_threadsched->setDisabled(true);
ui->gb_threadsched->setToolTip(tr("This feature is disabled for CPUs with less than %0 threads").arg(min_thread_count));
}
m_emu_settings->EnhanceComboBox(ui->preferredSPUThreads, emu_settings_type::PreferredSPUThreads, true);
SubscribeTooltip(ui->gb_spu_threads, tooltips.settings.preferred_spu_threads);
ui->preferredSPUThreads->setItemText(ui->preferredSPUThreads->findData(0), tr("Auto", "Preferred SPU threads"));

View File

@ -143,13 +143,6 @@
<string>Additional Settings</string>
</property>
<layout class="QVBoxLayout" name="checkboxes_layout">
<item>
<widget class="QCheckBox" name="enableScheduler">
<property name="text">
<string>Enable thread scheduler</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="lowerSPUThrPrio">
<property name="text">
@ -200,7 +193,7 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="coreTabRightLayout" stretch="0,0,0,0">
<layout class="QVBoxLayout" name="coreTabRightLayout" stretch="0,0,0,0,0">
<item>
<widget class="QGroupBox" name="gb_tsx">
<property name="sizePolicy">
@ -255,6 +248,24 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_threadsched">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Thread Scheduler</string>
</property>
<layout class="QVBoxLayout" name="gb_threadsched_layout">
<item>
<widget class="QComboBox" name="threadsched"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="coreTabRightLayoutSpacer">
<property name="orientation">

View File

@ -64,7 +64,7 @@ public:
const QString spu_llvm = tr("Recompiles and caches the game's SPU code using the LLVM Recompiler before running which adds extra start-up time.\nThis is the fastest option with very good compatibility.\nIf you experience issues, use the ASMJIT Recompiler.");
const QString accurate_xfloat = tr("Adds extra accuracy to SPU float vectors processing.\nFixes bugs in various games at the cost of performance.\nThis setting is only applied when SPU Decoder is set to Fast or LLVM.");
const QString spu_cache = tr("Caches compiled SPU modules on disc.\nShould normally stay enabled.\nDisable this if the cache becomes too large.\nDisabling it does not remove the existing cache.");
const QString enable_thread_scheduler = tr("Allows RPCS3 to manually schedule physical cores to run specific tasks on, instead of letting the OS handle it.\nVery useful on Windows, especially for AMD Ryzen systems where it can give huge performance gains.\nNote: This function is only implemented for AMD Ryzen CPUs.");
const QString enable_thread_scheduler = tr("Control how RPCS3 utilizes the threads of your system, only useful for 6C/12T CPUs or higher up.\nEach option heavily depends on the game and on your CPU, it's recommended to try each option to find out which performs the best.");
const QString lower_spu_thread_priority = tr("Runs SPU threads with lower priority than PPU threads.\nUsually faster on an i3 or i5, possibly slower or no difference on an i7 or Ryzen.");
const QString spu_loop_detection = tr("Try to detect loop conditions in SPU kernels and use them as scheduling hints.\nImproves performance and reduces CPU usage.\nMay cause severe audio stuttering in rare cases.");
const QString enable_tsx = tr("Enable usage of TSX instructions.\nNeeds to be forced on some Haswell or Broadwell CPUs.\nForcing this on older Hardware can lead to system instability, use it with caution.");