cluster.fork() 是否保证使用不同的 CPU 内核?
Is cluster.fork() guaranteed to use a different CPU core?
我看过很多关于在 node.js 中使用集群来利用所有 CPU 核心的教程,但它们似乎都暗示 运行 cluster.fork()
将使用新的 CPU 内核;例如:
if (cluster.isMaster) {
cluster.setupMaster({
exec: 'bin/www'
});
// Fork workers
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function (id) {
console.log('Worker id: ' + id + ' with pid: ' + cluster.workers[id].process.pid);
});
}
node.js documentation 出奇的糟糕,关于 cluster.fork([env])
的信息很少:
Spawn a new worker process.
This can only be called from the master process.
所以它只是说它产生了一个新的工作进程。我们怎么知道这将在一个新的 CPU 核心上产生,如果我们在每个 CPU 核心上已经有至少一个进程时产生一个额外的进程会发生什么?
以下是关于现代 OS 系统(例如 Linux、Windows、FreeBSD)上的进程和线程的一般要点。操作系统根据许多因素动态管理 thread/process 正在 运行 开启哪个内核(例如,哪个内核 'closest' 到保存进程数据的内存 [这在双核上有点重要CPU 台机器],哪个核心是空闲的,等等)。动态地,因为它可以很好地将核心时间片切换到时间片(例如每秒 60 次)。
不要忘记,在 SMP 硬件平台中,将线程从一个内核移动到另一个内核并没有真正的性能损失——这主要只是内核的程序计数器寄存器指向何处的问题。还有其余的进程上下文,但主要是一堆 CPU 寄存器值。实际上,如果您有 2 个或更多 CPUs,现代英特尔平台就不是纯 SMP。它们之间的 Quickpath 互连用于从实际上是 NUMA 的东西合成 SMP 硬件架构。 Quickpath 就像两台独立计算机之间的高速网络连接,速度足以传输数据、缓存同步等,这样保存在另一台 CPU 的 RAM 上的数据几乎可以像在这台计算机上一样快速访问CPU 的内存。
对于一个应用程序(例如 Node.JS 运行 时间)来说,要控制它最终 运行 在哪个内核上运行实际上是非常困难的,而且通常是毫无意义的;可以相信 OS 可以很好地管理它以获得最佳性能。采取手动控制是毫无意义的。我出于兴趣尝试了一次(使用一些实时信号处理代码),并且无法从系统中获得比简单地让 OS 代表我自然地管理核心亲和力更好的性能。
所以当你调用 cluster.fork() 时(假设 "spawn another worker process" 实际上意味着启动另一个进程)那么新进程将是 运行 OS 认为最适合当时的情况,并且会随着进程阻塞、准备好 运行、被另一个进程抢占等而不断围绕核心反弹。
产生比 CPU 核心更多的进程可能是一件复杂的事情。如果他们阻塞很多(例如等待输入)也没关系。在那种情况下,它们会阻塞,OS 会取消对它们的调度,如果某些数据出现在套接字上,或者重新安排任何必要的数据来处理数据。如果他们不断处理,那么最好将 processes/threads 的数量与 CPU 核心的数量相匹配,以最大限度地减少因上下文切换而损失的时间。
编辑
因此,您只是在碰碰运气,因为计算机中没有其他东西同时 运行 会阻止 OS 将您的 4 个进程分布在 4 个内核上。
如果您同时 运行正在使用文字处理器,那么当您不打字时,它大多处于静止状态(即被阻止等待键盘输入),所以没问题。 OS 不会(事实上,不能)安排等待输入的进程,直到输入数据实际到达。信号量、互斥量等也是如此
相比之下,启动 Web 浏览器并将其指向包含大量视频广告的页面会导致浏览器占用大量 CPU 时间。那是因为总是有数据要处理(视频流),解码它需要大量的数学运算。
还有进程优先级作为另一个可玩的维度。如果您已将您的进程标记为高优先级,那么 OS 会将它们安排在其他进程之前。
OSes schedule threads/processes 实现所有人的最大吞吐量,试图对系统中的每个进程公平。大多数 OSes 将以每秒大约 60 次的速度在每个内核上决定要 运行 什么。最终的结果是,看似一切都运行顺畅地并行,但实际上一切都在轮流进行。进程优先级是一种使 OS 在每秒做出 60 次决策时偏向更高优先级进程的方法。
Windows 的独特之处在于为当前具有鼠标焦点的进程提供了人为的优先级提升 - 使其看起来和感觉起来更加敏捷。我认为这可以追溯到 Windows 3.0!
不,操作系统决定进程将被调度到哪个内核运行。集群模块将简单地生成许多单独的 Node.js 进程,因此 可能 您的程序同时 运行 在多个内核上(并行).
这通常是通过让每个派生的 Node.js 进程成为服务器的一个单独实例(具有非共享内存)来实现的,所有进程都在同一端口上侦听。因此,您实际上是在服务器的多个实例之间拆分传入 HTTP 请求的工作负载。
我看过很多关于在 node.js 中使用集群来利用所有 CPU 核心的教程,但它们似乎都暗示 运行 cluster.fork()
将使用新的 CPU 内核;例如:
if (cluster.isMaster) {
cluster.setupMaster({
exec: 'bin/www'
});
// Fork workers
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function (id) {
console.log('Worker id: ' + id + ' with pid: ' + cluster.workers[id].process.pid);
});
}
node.js documentation 出奇的糟糕,关于 cluster.fork([env])
的信息很少:
Spawn a new worker process.
This can only be called from the master process.
所以它只是说它产生了一个新的工作进程。我们怎么知道这将在一个新的 CPU 核心上产生,如果我们在每个 CPU 核心上已经有至少一个进程时产生一个额外的进程会发生什么?
以下是关于现代 OS 系统(例如 Linux、Windows、FreeBSD)上的进程和线程的一般要点。操作系统根据许多因素动态管理 thread/process 正在 运行 开启哪个内核(例如,哪个内核 'closest' 到保存进程数据的内存 [这在双核上有点重要CPU 台机器],哪个核心是空闲的,等等)。动态地,因为它可以很好地将核心时间片切换到时间片(例如每秒 60 次)。
不要忘记,在 SMP 硬件平台中,将线程从一个内核移动到另一个内核并没有真正的性能损失——这主要只是内核的程序计数器寄存器指向何处的问题。还有其余的进程上下文,但主要是一堆 CPU 寄存器值。实际上,如果您有 2 个或更多 CPUs,现代英特尔平台就不是纯 SMP。它们之间的 Quickpath 互连用于从实际上是 NUMA 的东西合成 SMP 硬件架构。 Quickpath 就像两台独立计算机之间的高速网络连接,速度足以传输数据、缓存同步等,这样保存在另一台 CPU 的 RAM 上的数据几乎可以像在这台计算机上一样快速访问CPU 的内存。
对于一个应用程序(例如 Node.JS 运行 时间)来说,要控制它最终 运行 在哪个内核上运行实际上是非常困难的,而且通常是毫无意义的;可以相信 OS 可以很好地管理它以获得最佳性能。采取手动控制是毫无意义的。我出于兴趣尝试了一次(使用一些实时信号处理代码),并且无法从系统中获得比简单地让 OS 代表我自然地管理核心亲和力更好的性能。
所以当你调用 cluster.fork() 时(假设 "spawn another worker process" 实际上意味着启动另一个进程)那么新进程将是 运行 OS 认为最适合当时的情况,并且会随着进程阻塞、准备好 运行、被另一个进程抢占等而不断围绕核心反弹。
产生比 CPU 核心更多的进程可能是一件复杂的事情。如果他们阻塞很多(例如等待输入)也没关系。在那种情况下,它们会阻塞,OS 会取消对它们的调度,如果某些数据出现在套接字上,或者重新安排任何必要的数据来处理数据。如果他们不断处理,那么最好将 processes/threads 的数量与 CPU 核心的数量相匹配,以最大限度地减少因上下文切换而损失的时间。
编辑
因此,您只是在碰碰运气,因为计算机中没有其他东西同时 运行 会阻止 OS 将您的 4 个进程分布在 4 个内核上。
如果您同时 运行正在使用文字处理器,那么当您不打字时,它大多处于静止状态(即被阻止等待键盘输入),所以没问题。 OS 不会(事实上,不能)安排等待输入的进程,直到输入数据实际到达。信号量、互斥量等也是如此
相比之下,启动 Web 浏览器并将其指向包含大量视频广告的页面会导致浏览器占用大量 CPU 时间。那是因为总是有数据要处理(视频流),解码它需要大量的数学运算。
还有进程优先级作为另一个可玩的维度。如果您已将您的进程标记为高优先级,那么 OS 会将它们安排在其他进程之前。
OSes schedule threads/processes 实现所有人的最大吞吐量,试图对系统中的每个进程公平。大多数 OSes 将以每秒大约 60 次的速度在每个内核上决定要 运行 什么。最终的结果是,看似一切都运行顺畅地并行,但实际上一切都在轮流进行。进程优先级是一种使 OS 在每秒做出 60 次决策时偏向更高优先级进程的方法。
Windows 的独特之处在于为当前具有鼠标焦点的进程提供了人为的优先级提升 - 使其看起来和感觉起来更加敏捷。我认为这可以追溯到 Windows 3.0!
不,操作系统决定进程将被调度到哪个内核运行。集群模块将简单地生成许多单独的 Node.js 进程,因此 可能 您的程序同时 运行 在多个内核上(并行).
这通常是通过让每个派生的 Node.js 进程成为服务器的一个单独实例(具有非共享内存)来实现的,所有进程都在同一端口上侦听。因此,您实际上是在服务器的多个实例之间拆分传入 HTTP 请求的工作负载。