我可以理解如何编写一个使用多个进程或线程的程序:fork()一个新进程并使用IPC,或创建多个线程并使用这些通信机制.
我也理解上下文切换.也就是说,只有一次CPU,操作系统为每个进程安排时间(并且有大量的调度算法),从而我们实现了同时运行多个进程.
现在我们拥有多核处理器(或多处理器计算机),我们可以在两个独立的核心上同时运行两个进程.
我的问题是关于最后一个场景:内核如何控制进程运行的核心?哪些系统调用(在Linux,甚至是Windows中)在特定核心上安排进程?
我问的原因是:我正在为学校开展一个项目,我们将在那里探索最近的计算主题 - 我选择了多核架构.关于如何在这种环境中编程(如何监视死锁或竞争条件)似乎有很多材料,但在控制各个核心本身方面却没有太多.我希望能够编写一些演示程序并提供一些汇编指令或C代码,以实现"看,我在第二个内核上运行无限循环,查看该特定内核的 CPU利用率峰值" .
任何代码示例?还是教程?
编辑:为了澄清 - 很多人都说这是操作系统的目的,应该让操作系统处理这个问题.我完全同意!但那时我所要求的(或试图感受到)是操作系统实际上做的事情.不是调度算法,而是"一旦选择了核心,必须执行哪些指令才能让核心开始获取指令?"
如其他人提及的,处理器亲和性操作系统的特定.如果你想在操作系统的范围之外做到这一点,你会获得很多乐趣,我的意思是痛苦.
也就是说,其他人已经提到SetProcessAffinityMask
过Win32.没人提到Linux内核设置处理器亲和性的方法,所以我会这样做.您需要使用该sched_setaffinity(2)
功能.这是一个很好的教程如何.
通常,系统会决定运行应用程序的核心.但是,您可以将应用程序的"亲缘关系"设置为特定核心,以告知操作系统仅在该核心上运行应用程序.通常这不是一个好主意,但有一些罕见的情况可能有意义.
要在Windows中执行此操作,请使用任务管理器,右键单击该过程,然后选择"设置关联性".您可以使用SetThreadAffinityMask,SetProcessAffinityMask或SetThreadIdealProcessor等函数在Windows中以编程方式执行此操作.
ETA:
如果您对操作系统实际上如何进行调度感兴趣,您可能需要查看以下链接:
Wikipedia关于上下文切换的文章
维基百科有关安排的文章
在linux内核中调度
对于大多数现代操作系统,操作系统会安排一个线程在核心上执行一小段时间.当时间片到期,或者线程执行导致其自愿产生核心的IO操作时,OS将调度另一个线程在核心上运行(如果有任何线程准备好运行).确切地调度哪个线程取决于OS的调度算法.
上下文切换的确切实现细节依赖于CPU和OS.它通常涉及切换到内核模式,OS保存前一个线程的状态,加载新线程的状态,然后切换回用户模式并恢复新加载的线程.我上面链接的上下文切换文章有关于此的更多细节.
没有什么能告诉核心"现在开始运行这个过程".
核心没有看到进程,它只知道可执行代码和各种运行级别以及可执行指令的相关限制.
当计算机启动时,为简单起见,只有一个核心/处理器处于活动状态并且实际运行任何代码.然后,如果操作系统具有多处理器功能,它会通过一些特定于系统的指令激活其他内核,其他内核很可能从与其他内核完全相同的位置拾取并从那里运行.
那么调度程序所做的是通过操作系统内部结构(任务/进程/线程队列)查看并选择一个并将其标记为在其核心运行.然后,在任务再次处于等待状态(并且未标记为固定到特定核心)之前,在其他核上运行的其他调度程序实例将不会触及它.将任务标记为正在运行后,调度程序将执行切换到用户空间,并在之前暂停的位置恢复任务.
从技术上讲,没有任何东西可以阻止内核在同一时间运行完全相同的代码(并且许多未锁定的函数都可以),但除非编写代码以期望它,否则它可能会全身心投入.
场景更加奇怪,有更多奇特的内存模型(上面假设"通常的"线性单个工作内存空间),其中内核不一定都看到相同的内存,并且可能需要从其他内核的离合器中获取代码,但它更容易通过简单处理将任务固定在核心(带有SPU的AFAIK索尼PS3架构就是这样).
要查找处理器数量而不是使用/ proc / cpuinfo,只需运行:
nproc
要在一组特定的处理器上运行进程:
taskset --cpu-list 1,2 my_command
会说我的命令只能在cpu 1或2上运行。
要在执行4种不同操作的4个处理器上运行程序,请使用参数化。程序的参数告诉它做一些不同的事情:
for i in `seq 0 1 3`; do taskset --cpu-list $i my_command $i; done
一个很好的例子是处理数组中的8百万次运算,以便0到(2mil-1)进入处理器1,2mil到(4mil-1)进入处理器2,依此类推。
您可以通过使用apt-get / yum安装htop并在命令行运行来查看每个进程的负载:
htop