NUMA内存页面迁移开销

7
我需要找到 Linux 下与 NUMA 内存页面迁移 相关的开销。 请问有哪些工具可以使用?如果可能,能否给出一个示例?

你要将内存页面从哪里迁移到哪里?我们是在谈论简单的页面错误吗?还是NUMA机器试图获取非本地内存页面?你需要更详细地描述你想要实现什么。 - sarnold
你的机器是否提供了微内核,使您能够轻松设置和测试本地和远程页面访问? - sarnold
你的意思是从“numactl --hardware”收集到的跳数吗? - user1450099
@sarnold:是否有可能只使用一些高级工具来对页面迁移等进行性能分析,而不需要编写内核代码? - user1450099
我不确定什么是“可能性”与“容易性”,但我感觉你最好的选择可能是:(a)有关该机器的数据表(b)在该机器上运行的最小且最无用的内核——如果您必须测量时间,则不希望同时进行其他许多操作。 - sarnold
1个回答

5
如果您想了解系统是否进行了过多的远程节点内存访问,并且使用英特尔CPU,Intel's PMU有一个名为vtbwrun的实用程序来报告QPI / uncore活动。
如果您想查看执行页面迁移需要多长时间,可以测量对numactl软件包提供的numa_move_pages调用的持续时间。
这里是一个示例
/*
 * Test program to test the moving of a processes pages.
 *
 * (C) 2006 Silicon Graphics, Inc.
 *          Christoph Lameter <clameter@sgi.com>
 */
#include <stdio.h>
#include <stdlib.h>
#include "../numa.h"
#include <unistd.h>
#include <errno.h>

unsigned int pagesize;
unsigned int page_count = 32;

char *page_base;
char *pages;

void **addr;
int *status;
int *nodes;
int errors;
int nr_nodes;

struct bitmask *old_nodes;
struct bitmask *new_nodes;

int main(int argc, char **argv)
{
      int i, rc;

      pagesize = getpagesize();

      nr_nodes = numa_max_node()+1;

      old_nodes = numa_bitmask_alloc(nr_nodes);
        new_nodes = numa_bitmask_alloc(nr_nodes);
        numa_bitmask_setbit(old_nodes, 1);
        numa_bitmask_setbit(new_nodes, 0);

      if (nr_nodes < 2) {
            printf("A minimum of 2 nodes is required for this test.\n");
            exit(1);
      }

      setbuf(stdout, NULL);
      printf("migrate_pages() test ......\n");
      if (argc > 1)
            sscanf(argv[1], "%d", &page_count);

      page_base = malloc((pagesize + 1) * page_count);
      addr = malloc(sizeof(char *) * page_count);
      status = malloc(sizeof(int *) * page_count);
      nodes = malloc(sizeof(int *) * page_count);
      if (!page_base || !addr || !status || !nodes) {
            printf("Unable to allocate memory\n");
            exit(1);
      }

      pages = (void *) ((((long)page_base) & ~((long)(pagesize - 1))) + pagesize);

      for (i = 0; i < page_count; i++) {
            if (i != 2)
                  /* We leave page 2 unallocated */
                  pages[ i * pagesize ] = (char) i;
            addr[i] = pages + i * pagesize;
            nodes[i] = 1;
            status[i] = -123;
      }

      /* Move to starting node */
      rc = numa_move_pages(0, page_count, addr, nodes, status, 0);
      if (rc < 0 && errno != ENOENT) {
            perror("move_pages");
            exit(1);
      }

      /* Verify correct startup locations */
      printf("Page location at the beginning of the test\n");
      printf("------------------------------------------\n");

      numa_move_pages(0, page_count, addr, NULL, status, 0);
      for (i = 0; i < page_count; i++) {
            printf("Page %d vaddr=%p node=%d\n", i, pages + i * pagesize, status[i]);
            if (i != 2 && status[i] != 1) {
                  printf("Bad page state before migrate_pages. Page %d status %d\n",i, status[i]);
                  exit(1);
            }
      }

      /* Move to node zero */
      numa_move_pages(0, page_count, addr, nodes, status, 0);

      printf("\nMigrating the current processes pages ...\n");
      rc = numa_migrate_pages(0, old_nodes, new_nodes);

      if (rc < 0) {
            perror("numa_migrate_pages failed");
            errors++;
      }

      /* Get page state after migration */
      numa_move_pages(0, page_count, addr, NULL, status, 0);
      for (i = 0; i < page_count; i++) {
            printf("Page %d vaddr=%lx node=%d\n", i,
                  (unsigned long)(pages + i * pagesize), status[i]);
            if (i != 2) {
                  if (pages[ i* pagesize ] != (char) i) {
                        printf("*** Page contents corrupted.\n");
                        errors++;
                  } else if (status[i]) {
                        printf("*** Page on the wrong node\n");
                        errors++;
                  }
            }
      }

      if (!errors)
            printf("Test successful.\n");
      else
            printf("%d errors.\n", errors);

      return errors > 0 ? 1 : 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接