libnuma 及底层实现

编程入门 行业动态 更新时间:2024-10-10 19:25:15

libnuma 及<a href=https://www.elefans.com/category/jswz/34/1768082.html style=底层实现"/>

libnuma 及底层实现

libnuma是一个用于Linux系统的NUMA(非一致性内存访问)API。

libnuma提供了一组函数和工具,用于管理和优化NUMA系统中的内存分配和访问。

NUMA是一种计算机体系结构,其中多个处理器和内存模块通过高速互联网络连接在一起。在NUMA系统中,每个处理器都有自己的本地内存,但也可以访问其他处理器的内存。

libnuma的主要功能包括以下几个方面:

1. 内存分配:libnuma提供了一些函数,如numa_alloc_onnode和numa_alloc_local,用于在指定的NUMA节点上分配内存。这些函数可以确保内存分配在本地节点上,从而减少远程访问的开销。例如,以下代码将在NUMA节点0上分配1MB的内存:

void* mem = numa_alloc_onnode(1024*1024, 0);

2. 内存绑定:libnuma还提供了一些函数,如numa_bind和numa_set_bind_policy,用于将线程或进程绑定到指定的NUMA节点上。通过绑定,可以确保线程或进程只在指定的节点上执行,从而减少远程访问的开销。例如,以下代码将当前线程绑定到NUMA节点1上:

numa_bind(numa_parse_nodestring("1"));

3. 内存迁移:libnuma提供了一些函数,如numa_migrate_pages和numa_migrate_hint,用于在NUMA节点之间迁移内存页面。通过迁移,可以将访问频率较高的页面移动到本地节点上,从而提高内存访问的效率。例如,以下代码将页面从NUMA节点0迁移到NUMA节点1:

unsigned long nodemask = 1UL << 1;
numa_migrate_pages(0, nodemask);

4. NUMA信息查询:libnuma提供了一些函数,如numa_num_configured_nodes和numa_node_size,用于查询系统中的NUMA节点数量和每个节点的内存大小。这些信息可以帮助开发人员了解系统的NUMA配置,并根据需要进行优化。例如,以下代码将打印系统中的NUMA节点数量和每个节点的内存大小:

int num_nodes = numa_num_configured_nodes();
for (int i = 0; i < num_nodes; i++) {long size = numa_node_size(i, NULL);printf("Node %d: %ld bytes\n", i, size);
}

通过上述功能,libnuma可以帮助开发人员更好地管理和优化NUMA系统中的内存分配和访问。下面举几个例子来说明其使用方法和效果。

例子1:内存分配和绑定

假设我们有一个NUMA系统,其中有两个节点,每个节点有4个处理器核心和8GB的内存。我们希望在节点0上分配1GB的内存,并将线程绑定到节点1上。可以使用以下代码实现:

void* mem = numa_alloc_onnode(1024*1024*1024, 0);
numa_bind(numa_parse_nodestring("1"));

这样,我们就在节点0上分配了1GB的内存,并将当前线程绑定到节点1上。

例子2:内存迁移

假设我们有一个NUMA系统,其中有两个节点,每个节点有4个处理器核心和8GB的内存。我们发现某个页面在节点0上的访问频率很高,希望将其迁移到节点1上以提高访问效率。可以使用以下代码实现:

unsigned long nodemask = 1UL << 1;
numa_migrate_pages(0, nodemask);

这样,我们就将页面从节点0迁移到节点1。

例子3:NUMA信息查询

假设我们想了解系统中的NUMA节点数量和每个节点的内存大小。可以使用以下代码实现:

int num_nodes = numa_num_configured_nodes();
for (int i = 0; i < num_nodes; i++) {long size = numa_node_size(i, NULL);printf("Node %d: %ld bytes\n", i, size);
}

这样,就可以打印出系统中的NUMA节点数量和每个节点的内存大小。

通过以上例子,可以更好地理解libnuma的使用方法和效果。libnuma提供了一组函数和工具,用于管理和优化NUMA系统中的内存分配和访问,可以帮助开发人员充分利用NUMA系统的性能优势。

 #include <numa.h>cc ... -lnumaint numa_available(void);int numa_max_possible_node(void);int numa_num_possible_nodes();int numa_max_node(void);int numa_num_configured_nodes();struct bitmask *numa_get_mems_allowed(void);int numa_num_configured_cpus(void);struct bitmask *numa_all_nodes_ptr;struct bitmask *numa_no_nodes_ptr;struct bitmask *numa_all_cpus_ptr;int numa_num_task_cpus();int numa_num_task_nodes();int numa_parse_bitmap(char *line , struct bitmask *mask);struct bitmask *numa_parse_nodestring(const char *string);struct bitmask *numa_parse_nodestring_all(const char *string);struct bitmask *numa_parse_cpustring(const char *string);struct bitmask *numa_parse_cpustring_all(const char *string);long numa_node_size(int node, long *freep);long long numa_node_size64(int node, long long *freep);int numa_preferred(void);void numa_set_preferred(int node);int numa_get_interleave_node(void);struct bitmask *numa_get_interleave_mask(void);void numa_set_interleave_mask(struct bitmask *nodemask);void numa_interleave_memory(void *start, size_t size, structbitmask *nodemask);void numa_bind(struct bitmask *nodemask);void numa_set_localalloc(void);void numa_set_membind(struct bitmask *nodemask);void numa_set_membind_balancing(struct bitmask *nodemask);struct bitmask *numa_get_membind(void);void *numa_alloc_onnode(size_t size, int node);void *numa_alloc_local(size_t size);void *numa_alloc_interleaved(size_t size);void *numa_alloc_interleaved_subset(size_t size,  struct bitmask*nodemask); void *numa_alloc(size_t size);void *numa_realloc(void *old_addr, size_t old_size, size_tnew_size);void numa_free(void *start, size_t size);int numa_run_on_node(int node);int numa_run_on_node_mask(struct bitmask *nodemask);int numa_run_on_node_mask_all(struct bitmask *nodemask);struct bitmask *numa_get_run_node_mask(void);void numa_tonode_memory(void *start, size_t size, int node);void numa_tonodemask_memory(void *start, size_t size, structbitmask *nodemask);void numa_setlocal_memory(void *start, size_t size);void numa_police_memory(void *start, size_t size);void numa_set_bind_policy(int strict);void numa_set_strict(int strict);int numa_distance(int node1, int node2);int numa_sched_getaffinity(pid_t pid, struct bitmask *mask);int numa_sched_setaffinity(pid_t pid, struct bitmask *mask);int numa_node_to_cpus(int node, struct bitmask *mask);void numa_node_to_cpu_update();int numa_node_of_cpu(int cpu);struct bitmask *numa_allocate_cpumask();void numa_free_cpumask();struct bitmask *numa_allocate_nodemask();void numa_free_nodemask();struct bitmask *numa_bitmask_alloc(unsigned int n);struct bitmask *numa_bitmask_clearall(struct bitmask *bmp);struct bitmask *numa_bitmask_clearbit(struct bitmask *bmp,unsigned int n);int numa_bitmask_equal(const struct bitmask *bmp1, const structbitmask *bmp2);void numa_bitmask_free(struct bitmask *bmp);int numa_bitmask_isbitset(const struct bitmask *bmp, unsigned intn);unsigned int numa_bitmask_nbytes(struct bitmask *bmp);struct bitmask *numa_bitmask_setall(struct bitmask *bmp);struct bitmask *numa_bitmask_setbit(struct bitmask *bmp, unsignedint n);void copy_bitmask_to_nodemask(struct bitmask *bmp, nodemask_t*nodemask)void copy_nodemask_to_bitmask(nodemask_t *nodemask, structbitmask *bmp)void copy_bitmask_to_bitmask(struct bitmask *bmpfrom, structbitmask *bmpto)unsigned int numa_bitmask_weight(const struct bitmask *bmp )int numa_move_pages(int pid, unsigned long count, void **pages,const int *nodes, int *status, int flags);int numa_migrate_pages(int pid, struct bitmask *fromnodes, structbitmask *tonodes);void numa_error(char *where);extern int numa_exit_on_error;extern int numa_exit_on_warn;void numa_warn(int number, char *where, ...);

numa_migrate_pages系统调用,内核中是kernel_migrate_pages服务函数,以X86体系结构作为说明

内核代码流程:

kernel_migrate_pages[mm/mempolicy.c]

do_migrate_pages.part.31()

migrate_to_node

        queue_pages_range

              walk_page_range

migrate_pages[mm/migrate.c]

        PageHuge

        unmap_and_move_huge_page/ unmap_and_move

              __unmap_and_move

lock_page(page);                     //获得页面锁

              get_new_page

               try_to_unmap[mm/rmap.c]

rmap_walk

rmap_walk_anon/ rmap_walk_ksm/ rmap_walk_file

try_to_unmap_one (rwc->rmap_one)

     flush_cache_page          //flush cache

ptep_clear_flush

flush_tlb_mm_range//flush TLB(包括remote核)

                 flush_tlb_func_local

                     flush_tlb_func_common                                               flush_tlb_others(=native_flush_tlb_others)

                                                           flush_tlb_func_remote

                 page_mapped

                     move_to_new_page   //真正的页面移动(拷贝)

                                   ……

                     remove_migration_ptes

                                   ……

参考文献:

Flush-Cache/Page-Lock/Flush-TLB说明 - CodeAntenna

Flush-Cache/Page-Lock/Flush-TLB说明_flush cache-CSDN博客

更多推荐

libnuma 及底层实现

本文发布于:2023-11-17 13:07:39,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1642778.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:底层   libnuma

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!