我想知道为什么与同一线程上的异步操作相比,上下文切换很慢。
为什么最好运行 N 个线程(N 等于内核数),每个线程异步处理 M 个客户端,而不是运行 M 个线程?我已经告诉过原因是上下文切换开销,但我找不到上下文切换有多慢。
我想知道为什么与同一线程上的异步操作相比,上下文切换很慢。
为什么最好运行 N 个线程(N 等于内核数),每个线程异步处理 M 个客户端,而不是运行 M 个线程?我已经告诉过原因是上下文切换开销,但我找不到上下文切换有多慢。
为了澄清起见,我假设当您说“而不是运行 M 个线程”时,您的意思是 N*M 个线程(如果您运行 M 个线程,每个线程都需要处理 N 个客户端以匹配相同数量的客户端总数,而这将是类似的情况)。
因此,在 N 个内核中运行的 N 个线程、每个处理 M 个客户端和在相同数量的内核中运行的 N*M 个线程之间的区别在于,在第一种情况下,您不必创建新线程,并且正如您所说,你不会有上下文切换。这是一个优势,因为创建 OS 线程所需的工作量很大;它需要创建不同的进程空间、新堆栈等。此外,如果您有更多线程,操作系统调度程序将停止并激活正在运行的进程,这也很耗时。每次调度程序更改分配给核心的进程时,它可能还需要缓存该进程的上下文,从而增加大量缓存未命中并因此增加时间。
另一方面,如果您有固定数量的线程,等于内核数(有时甚至建议 N-1),您可以在用户级调度程序中管理“任务”或客户端,这可能会在几个对程序进行更多计算,但避免大量操作系统进程和内存管理,从而使整体执行速度更快。一些当前的并行 API,例如 .Net 任务并行库 (TPL)、OpenMP、英特尔的线程构建模块或 Cilk 体现了这种称为动态多线程的并行模型。