管理处理器的亲和性

上传人:第*** 文档编号:42437058 上传时间:2018-06-02 格式:DOC 页数:4 大小:53KB
返回 下载 相关 举报
管理处理器的亲和性_第1页
第1页 / 共4页
管理处理器的亲和性_第2页
第2页 / 共4页
管理处理器的亲和性_第3页
第3页 / 共4页
管理处理器的亲和性_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《管理处理器的亲和性》由会员分享,可在线阅读,更多相关《管理处理器的亲和性(4页珍藏版)》请在金锄头文库上搜索。

1、软亲和性(affinity) 意味着进程并不会在处理器之间频繁迁移,而 硬亲和性 (affinity) 则意味着进程需要在您指定的处理器上运行。本文介绍了当前的亲和性 (affinity)机制,解释为什么和如何使用亲和性(affinity),并给出了几个样例代码 来显示如何使用这种功能。 简单地说,CPU 亲和性(affinity) 就是进程要在某个给定的 CPU 上尽量长时间地运行 而不被迁移到其他处理器的倾向性。Linux 内核进程调度器天生就具有被称为 软 CPU 亲 和性(affinity) 的特性,这意味着进程通常不会在处理器之间频繁迁移。这种状态正是 我们希望的,因为进程迁移的频率

2、小就意味着产生的负载小。 2.6 版本的 Linux 内核还包含了一种机制,它让开发人员可以编程实现 硬 CPU 亲和性 (affinity)。这意味着应用程序可以显式地指定进程在哪个(或哪些)处理器上运行。 什么是什么是 LinuxLinux 内核硬亲和性(内核硬亲和性(affinityaffinity)?)? 在 Linux 内核中,所有的进程都有一个相关的数据结构,称为 task_struct。这个结构非 常重要,原因有很多;其中与 亲和性(affinity)相关度最高的是 cpus_allowed 位掩码。 这个位掩码由 n 位组成,与系统中的 n 个逻辑处理器一一对应。 具有 4 个

3、物理 CPU 的 系统可以有 4 位。如果这些 CPU 都启用了超线程,那么这个系统就有一个 8 位的位掩码。如果为给定的进程设置了给定的位,那么这个进程就可以在相关的 CPU 上运行。因此,如 果一个进程可以在任何 CPU 上运行,并且能够根据需要在处理器之间进行迁移,那么位掩 码就全是 1。实际上,这就是 Linux 中进程的缺省状态。 Linux 内核 API 提供了一些方法,让用户可以修改位掩码或查看当前的位掩码: sched_set_affinity() (用来修改位掩码) sched_get_affinity() (用来查看当前的位掩码) 注意,cpu_affinity 会被传递给

4、子线程,因此应该适当地调用 sched_set_affinity。 为什么应该使用硬亲和性(为什么应该使用硬亲和性(affinityaffinity)?)? 通常 Linux 内核都可以很好地对进程进行调度,在应该运行的地方运行进程(这就是说, 在可用的处理器上运行并获得很好的整体性能)。内核包含了一些用来检测 CPU 之间任务 负载迁移的算法,可以启用进程迁移来降低繁忙的处理器的压力。 一般情况下,在应用程序中只需使用缺省的调度器行为。然而,您可能会希望修改这些缺 省行为以实现性能的优化。让我们来看一下使用硬亲和性(affinity) 的 3 个原因。 原因原因 1.1. 有大量计算要做有大

5、量计算要做 基于大量计算的情形通常出现在科学和理论计算中,但是通用领域的计算也可能出现这种 情况。一个常见的标志是您发现自己的应用程序要在多处理器的机器上花费大量的计算时 间。 原因原因 2.2. 您在测试复杂的应用程序您在测试复杂的应用程序 测试复杂软件是我们对内核的亲和性(affinity)技术感兴趣的另外一个原因。考虑一个 需要进行线性可伸缩性测试的应用程序。有些产品声明可以在 使用更多硬件 时执行得更 好。 我们不用购买多台机器(为每种处理器配置都购买一台机器),而是可以: 购买一台多处理器的机器 不断增加分配的处理器 测量每秒的事务数 评估结果的可伸缩性 如果应用程序随着 CPU 的

6、增加可以线性地伸缩,那么每秒事务数和 CPU 个数之间应该会 是线性的关系(例如斜线图 请参阅下一节的内容)。这样建模可以确定应用程序是 否可以有效地使用底层硬件。 Amdahl 法则说明这种加速比在现实中可能并不会发生, 但是可以非常接近于该值。对于通常情况来说,我们 可以推论出每个程序都有一些串行的组件。随着问题 集不断变大,串行组件最终会在优化解决方案时间方 面达到一个上限。 Amdahl 法则在希望保持高 CPU 缓存命中率时尤其重 要。如果一个给定的进程迁移到其他地方去了,那么 它就失去了利用 CPU 缓存的优势。实际上,如果正在 使用的 CPU 需要为自己缓存一些特殊的数据,那么所

7、 有其他 CPU 都会使这些数据在自己的缓存中失效。 因此,如果有多个线程都需要相同的数据,那么将这 些线程绑定到一个特定的 CPU 上是非常有意义的,这 样就确保它们可以访问相同的缓存数据(或者至少可 以提高缓存的命中率)。否则,这些线程可能会在不 同的 CPU 上执行,这样会频繁地使其他缓存项失效。 原因原因 3.3. 您正在运行时间敏感的、决定性的进程您正在运行时间敏感的、决定性的进程 我们对 CPU 亲和性(affinity)感兴趣的最后一个原因是实时(对时间敏感的)进程。例 如,您可能会希望使用硬亲和性(affinity)来指定一个 8 路主机上的某个处理器,而同 时允许其他 7 个

8、处理器处理所有普通的系统调度。这种做法确保长时间运行、对时间敏感 的应用程序可以得到运行,同时可以允许其他应用程序独占其余的计算资源。 下面的样例应用程序显示了这是如何工作的。 如何利用硬亲和性(如何利用硬亲和性(affinityaffinity) 现在让我们来设计一个程序,它可以让 Linux 系统非常繁忙。可以使用前面介绍的系统调 用和另外一些用来说明系统中有多少处理器的 API 来构建这个应用程序。实际上,我们的 目标是编写这样一个程序:它可以让系统中的每个处理器都繁忙几秒钟。 清单清单 1.1. 让处理器繁忙让处理器繁忙/* This method will create thread

9、s, then bind each to its own cpu. */ bool do_cpu_stress(int numthreads) int ret = TRUE;int created_thread = 0;/* We need a thread for each cpu we have. */while ( created_thread numthreads - 1 )int mypid = fork();if (mypid = 0) /* Child process */printf(“tCreating Child Thread: #%in“, created_thread)

10、;break;AmdahlAmdahl 法则法则 Amdahl 法则是有关使用并行处 理器来解决问题相对于只使用一 个串行处理器来解决问题的加速 比的法则。加速比(Speedup) 等于串行执行(只使用一个处理 器)的时间除以程序并行执行 (使用多个处理器)的时间: T(1) S = -T(j)其中 T(j) 是在使用 j 个处理 器执行程序时所花费的时间。else /* Only parent executes this */* Continue looping until we spawned enough threads! */ ;created_thread+;/* NOTE: All

11、 threads execute code from here down! */正如您可以看到的一样,这段代码只是通过 fork 调用简单地创建一组线程。每个线程都 执行这个方法中后面的代码。现在我们让每个线程都将亲和性(affinity)设置为自己的 CPU。 清单清单 2.2. 为每个线程设置为每个线程设置 CPUCPU 亲和性(亲和性(affinityaffinity)cpu_set_t mask;/* CPU_ZERO initializes all the bits in the mask to zero. */CPU_ZERO( /* CPU_SET sets only the b

12、it corresponding to cpu. */CPU_SET( created_thread, /* sched_setaffinity returns 0 in success */if( sched_setaffinity( 0, sizeof(mask), 如果程序可以执行到这儿,那么我们的线程就已经设置了自己的亲和性(affinity)。调 用 sched_setaffinity 会设置由 pid 所引用的进程的 CPU 亲和性(affinity)掩码。如 果 pid 为 0,那么就使用当前进程。 亲和性(affinity)掩码是使用在 mask 中存储的位掩码来表示的。最低位

13、对应于系统中 的第一个逻辑处理器,而最高位则对应于系统中最后一个逻辑处理器。 每个设置的位都对应一个可以合法调度的 CPU,而未设置的位则对应一个不可调度的 CPU。换而言之,进程都被绑定了,只能在那些对应位被设置了的处理器上运行。通常,掩 码中的所有位都被置位了。这些线程的亲和性(affinity)都会传递给从它们派生的子进 程中。 注意不应该直接修改位掩码。应该使用下面的宏。虽然在我们的例子中并没有全部使用这 些宏,但是在本文中还是详细列出了这些宏,您在自己的程序中可能需要这些宏。 清单清单 3.3. 间接修改位掩码的宏间接修改位掩码的宏void CPU_ZERO (cpu_set_t *

14、set) 这个宏对 CPU 集 set 进行初始化,将其设置为空集。void CPU_SET (int cpu, cpu_set_t *set)这个宏将 cpu 加入 CPU 集 set 中。void CPU_CLR (int cpu, cpu_set_t *set) 这个宏将 cpu 从 CPU 集 set 中删除。int CPU_ISSET (int cpu, const cpu_set_t *set) 如果 cpu 是 CPU 集 set 的一员,这个宏就返回一个非零值(true),否则就返回零 (false)。对于本文来说,样例代码会继续让每个线程都执行某些计算量较大的操作。 清单清单

15、 4.4. 每个线程都执行一个计算敏感的操作每个线程都执行一个计算敏感的操作/* Now we have a single thread bound to each cpu on the system */int computation_res = do_cpu_expensive_op(41);cpu_set_t mycpuid;sched_getaffinity(0, sizeof(mycpuid), if ( check_cpu_expensive_op(computation_res) )printf(“SUCCESS: Thread completed, and PASSED int

16、egrity check!n“,mycpuid);ret = TRUE;elseprintf(“FAILURE: Thread failed integrity check!n“,mycpuid);ret = FALSE;return ret; 现在您已经了解了在 Linux 2.6 版本的内核中设置 CPU 亲和性(affinity)的基本知识。 接下来,我们使用一个 main 程序来封装这些方法,它使用一个用户指定的参数来说明要 让多少个 CPU 繁忙。我们可以使用另外一个方法来确定系统中有多少个处理器: int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF); 这个方法让程序能够自己确定要让多少个处理器保持繁忙,例如缺省让所有的处理器都处 于繁忙状态,并允许用户指定系统中实际处理器范围的一个子集。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号