【问题标题】:Performance implications of context switches for 64-bit segment bases上下文切换对 64 位段库的性能影响
【发布时间】:2013-01-17 22:00:13
【问题描述】:

我对@9​​87654321@ 手册页中的措辞感到困惑。具体来说,它指出:

64 位段库的上下文切换相当昂贵。它可能 是使用段选择器设置 32 位基数的更快替代方案 通过使用 modify_ldt(2) 或使用 set_thread_area(2) 设置 LDT 内核 2.5 或更高版本中的系统调用。 arch_prctl() 仅在以下情况下才需要 您想设置大于 4GB 的基数。记忆在第一 使用 mmap(2) 可以分配 2GB 的地址空间 MAP_32BIT 标志。

这是否意味着使用此系统调用的进程的上下文切换会受到性能损失或确切的影响是什么?

查看 Linux 内核的源代码后,似乎对于小于 4 GiB 的地址使用 LDT,而大于 4 GiB 的地址使用特定于模型的寄存器。

来自do_arch_prctl

case ARCH_SET_FS:
        /* handle small bases via the GDT because that's faster to
           switch. */
        if (addr <= 0xffffffff) {
                set_32bit_tls(task, FS_TLS, addr);
                if (doit) {
                        load_TLS(&task->thread, cpu);
                        loadsegment(fs, FS_TLS_SEL);
                }
                task->thread.fsindex = FS_TLS_SEL;
                task->thread.fs = 0;
        } else {
                task->thread.fsindex = 0;
                task->thread.fs = addr;
                if (doit) {
                        /* set the selector to 0 to not confuse
                           __switch_to */
                        loadsegment(fs, 0);
                        ret = wrmsrl_safe(MSR_FS_BASE, addr);
                }
        }
        put_cpu();
        break;

如何使用 GDT 比写入寄存器更快?另外,我假设更新FS和GS的价格只在进程之间切换时支付,这意味着当没有其他进程计划运行时,通过系统调用进入内核没有额外费用?

【问题讨论】:

    标签: c linux performance x86-64 cpu-registers


    【解决方案1】:

    哇,这是在 12 月提出的,但没有人回答?其中一些您可能已经知道,如果知道,我深表歉意。

    这只是因为执行 wrmsr 的步骤很慢。任务切换时只加载段寄存器更容易更快。

    在非常现代的 Intel 处理器上,“rdfsbase”、“wrfsbase”、“rdgsbase”和“wrgsbase”指令的添加允许直接访问 FS 和 GS 的基址寄存器,难度大大低于以前。事实上,如果内核愿意,它可以允许在用户模式下使用它们。您可能想检查现代 Linux 内核是否利用 wrfsbase 来使分配低于 4 GB 的 TLS 区域变得不必要。

    我不知道它在 Linux 上的情况如何,但从 Windows 7 开始的 Windows NT 具有用户模式线程调度作为应用程序开发人员的可选功能。与 Linux 和 Mac OS X 中一样,Windows 使用段寄存器的基地址在 x86 上实现线程本地存储(x86-64 Windows 中的 GS)。这个特性与 Fiber 类似,只是一个程序可以将自己的线程上下文切换到另一个线程上下文,这种方式也被内核识别。

    Windows 中的用户模式调度是通过为每个可调度线程创建一个带有指向 TLS 块(在 Windows 中称为“线程环境块”或 TEB)的段的 LDT 来实现的。除了上下文切换之外,用户模式还可以通过重新加载 GS 基础来切换线程。这要求 TEB 低于 Linux 的 arch_prctl 的性能说明中的 2^32 - 否则,用户模式调度将需要在每次切换到不同的线程时调用 NT 内核以执行 wrmsr,从而破坏了整点用户模式调度。

    在 Windows 8.1 中,添加了对 wrgsbase 的支持,并且还为用户模式启用了它。 8.1 中的用户模式调度使用 wrgsbase 而不是 GS 段重新加载和 LDT(如果 CPU 有)。

    【讨论】:

      猜你喜欢
      • 2015-05-18
      • 1970-01-01
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-13
      • 1970-01-01
      相关资源
      最近更新 更多