Linux对NUMA技术的支持。

来源:互联网 发布:修改电脑mac地址 编辑:程序博客网 时间:2024/06/06 01:59

并行计算的背景:

自计算机诞生之日起,对其提供更强计算能力的追求始终没有间断。早期的计算机通过不断地提高时钟频率来加快处理速度。现在,时钟的问题越来越遇到限制,根据爱因斯坦相对论,电子的速度不会超过光速,频率的不断提高,意味着电子信号从一段到达另一端的距离就要越短,计算机就要不断变小。但是,伴随时钟的加快,处理器的热量也急剧增大,散热部件必不可少,迫使计算机的体积不可能无限制的减小,通过加快时钟来增强计算能力的方法遇到了瓶颈。

既然不能将计算机无限变小,那么就尝试另一种思路,通过扩展计算单元的数量,达到增强计算能力的目的。于是就有了多处理机系统,包括并行计算机,以及分布式计算机系统。NUMA(Non Uniform Memory Access)作为多处理机系统一种典型架构,具有区别于其他多处理机系统的特性。

1.具有对所有CPU可见的统一的地址空间

2.通过LOAD、STORE指令访问远端存储器

3.访问远端存储器的速度低于访问本地存储器


NUMA系统简介:

NUMA(Non Uniform Memory Access),即非一致内存访问,是针对UMA(Uniform Memory Access)提出的。典型的UMA架构,如SMP(Symmetric MultiProcessing)机器,多个CPU以及一个或多个主存储器模块通过一条系统总线通信。随着系统规模的扩大,CPU数量不断增加,对系统总线的争抢现象越发严重,系统总线带宽成为了多CPU访存的瓶颈。

NUMA架构下,多CPU对主存的访问并非对等的,每个CPU都有自己的主存, CPU与自己的主存物理上距离更近,访问速度更快,而访问远端存储器的速度相对要慢。NUMA用Node来管理CPU与主存。一个NUMA系统由多个NUMA Node组成,其中每个Node可以拥有多个CPU,但是只有一个内存控制器,保证本Node的所有CPU对本Node的主存实现对等访问,而其它Node的CPU对本Node的主存访问延迟要大一些。


NUMA系统的启动流程:

系统加电,对于单CPU机器,CPU直接执行BIOS程序,但是对于多处理机系统,由哪个CPU执行该程序是个问题。针对这个问题,Intel提出了Multiple Processor Initialization Protocol,该协议规定了两种类型的CPU,作为主启动CPU的BSP(Bootstrap Processor),作为应用服务CPU的AP(Application Processor),系统加电后通过主板上的硬件选择机制,选择一个CPU作为BSP,而将其它CPU作为AP。(具体的协议与选择算法细节,参考《IA-32 Architectures Software Developer's Manual 3A》,Chapter 7,Multiple Processor Management)[1]在BSP上执行BIOS程序,读取/设置CMOS相关信息,并完成自检程序,为其它AP建立管理列表,此时所有AP均处于空转状态。

Linux通过读取系统的firmware中的ACPI表,获得NUMA系统的CPU及物理内存分布信息,最重要的是SRAT(System Resource Affinity Table)和SLIT(System Locality Information Table)。SRAT中包含两个结构,Processor Local APIC/SAPIC Affinity Structure用于记录CPU信息,Memory Affinity Structure用于记录主存信息[3]。Linux kernel中通过include/acpi/actbl1.h中acpi_table_slit与acpi_table_srat记录SLIT与SRAT结构信息,通过acpi_numa_init()函数读取系统firmware中的数据,赋值给以上两个结构,用于NUMA系统初始化。代码(以Linux2.6.36 kernel为例)如下: 

start_kernel()(init/main.c) -> setup_arch()(arch/x86/kernel/setup.c) -> acpi_numa_init()(drivers/acpi/numa.c)

[cpp] view plaincopy
  1. <span style="font-size:14px;">int __init acpi_numa_init(void)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     /* SRAT: Static Resource Affinity Table */  
  6.     if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {  
  7.         acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,  
  8.                      acpi_parse_x2apic_affinity, nr_cpu_ids);  
  9.         acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,  
  10.                      acpi_parse_processor_affinity, nr_cpu_ids);  
  11.         ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,  
  12.                         acpi_parse_memory_affinity,  
  13.                         NR_NODE_MEMBLKS);  
  14.     }  
  15.   
  16.     /* SLIT: System Locality Information Table */  
  17.     acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);  
  18.   
  19.     acpi_numa_arch_fixup();  
  20.     return ret;  
  21. }  
  22.   
  23. 相关结构在文件include/acpi/actbl1.h中:  
  24. /******************************************************************************* 
  25.  * 
  26.  * SLIT - System Locality Distance Information Table 
  27.  *        Version 1 
  28.  * 
  29.  ******************************************************************************/  
  30.   
  31. struct acpi_table_slit {  
  32.     struct acpi_table_header header;    /* Common ACPI table header */  
  33.     u64 locality_count;  
  34.     u8 entry[1];        /* Real size = localities^2 */  
  35. };  
  36.   
  37. /******************************************************************************* 
  38.  * 
  39.  * SRAT - System Resource Affinity Table 
  40.  *        Version 3 
  41.  * 
  42.  ******************************************************************************/  
  43.   
  44. struct acpi_table_srat {  
  45.     struct acpi_table_header header;    /* Common ACPI table header */  
  46.     u32 table_revision; /* Must be value '1' */  
  47.     u64 reserved;       /* Reserved, must be zero */  
  48. };  
  49.   
  50. /* Values for subtable type in struct acpi_subtable_header */  
  51.   
  52. enum acpi_srat_type {  
  53.     ACPI_SRAT_TYPE_CPU_AFFINITY = 0,  
  54.     ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1,  
  55.     ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,  
  56.     ACPI_SRAT_TYPE_RESERVED = 3 /* 3 and greater are reserved */  
  57. };  
  58.   
  59. /* 
  60.  * SRAT Sub-tables, correspond to Type in struct acpi_subtable_header 
  61.  */  
  62.   
  63. /* 0: Processor Local APIC/SAPIC Affinity */  
  64.   
  65. struct acpi_srat_cpu_affinity {  
  66.     struct acpi_subtable_header header;  
  67.     u8 proximity_domain_lo;  
  68.     u8 apic_id;  
  69.     u32 flags;  
  70.     u8 local_sapic_eid;  
  71.     u8 proximity_domain_hi[3];  
  72.     u32 reserved;       /* Reserved, must be zero */  
  73. };  
  74.   
  75. /* Flags */  
  76.   
  77. #define ACPI_SRAT_CPU_USE_AFFINITY  (1) /* 00: Use affinity structure */  
  78.   
  79. /* 1: Memory Affinity */  
  80.   
  81. struct acpi_srat_mem_affinity {  
  82.     struct acpi_subtable_header header;  
  83.     u32 proximity_domain;  
  84.     u16 reserved;       /* Reserved, must be zero */  
  85.     u64 base_address;  
  86.     u64 length;  
  87.        u32 reserved1;  
  88.     u32 flags;  
  89.        u64 reserved2;          /* Reserved, must be zero */  
  90. };  
  91. </span>  
0 0
原创粉丝点击