将页面预取到 RAM

问题描述

我正在编写一个高度优化的 AVL 树,现在我决定处理在插入过程中遇到的多个页面错误。原来,我只是试图访问另一个产生页面错误的页面。我尝试在插入代码的不同位置以多种组合使用 gcc 的内置预取函数,但没有成功摆脱它们。我还尝试通过执行 *ptr = *ptr 进行一些试验,看看它是否会产生任何影响(ptr 是我想要访问的指针,它每隔一段时间就会产生一个页面错误)。
更多背景:我使用 malloc 来获取 AVL 树的内存,然后在内存中“前进”(如“每个新插入都以线性顺序添加一个新节点”)。因此,很自然地,每次 x 插入我都试图访问一个新页面,从而产生一个页面错误。我尝试预取指针本身和指针后几个字节的指针(以确保它在新页面上),我尝试将预取的指针对齐到 64 字节。也许内置的预取指令只适用于缓存而不实际加载页面,我不知道。
目标是在访问该页面之前将该页面放入内存中,这样我就不会出现页面错误并减慢速度(每次测试进行数百万次插入,因此实际上每隔一段时间实际上变得非常频繁并且出现大量数字)。
GCC 9.2.0 目标 mingw32,Windows 10 64 位
代码:

struct net_avl_node {
  int sfd;
  int balance;
  void (*value)(int);
  struct net_avl_node* restrict parent;
  struct net_avl_node* restrict left;
  struct net_avl_node* restrict right;
};

struct net_avl_tree {
  struct net_avl_node** parts;
  struct net_avl_node* restrict head;
  struct net_avl_node* last;
  uint32_t count;
  uint32_t amount;
  uint32_t max_items_per_part;
};

int net_avl_insert(struct net_avl_tree* const tree,const int sfd,void (*callback)(int)) {
  void* restrict ptr;
  struct net_avl_node* restrict node = tree->head;
  struct net_avl_node* restrict temp;
  if(tree->amount == 0) { // first object becomes the head
    ptr = malloc(sizeof(struct net_avl_node*));
    if(ptr == NULL) {
      return ENOMEM;
    }
    tree->parts = ptr;
    ptr = malloc(sizeof(struct net_avl_node) * tree->max_items_per_part);
    if(ptr == NULL) {
      free(tree->parts);
      return ENOMEM;
    }
    //memset(ptr,sizeof(struct net_avl_node) * tree->max_items_per_part);
    // didn't change anything
    tree->parts[0] = ptr;
    tree->parts[0][0] = (struct net_avl_node) {
      .sfd = sfd,.balance = 0,.value = callback,.parent = NULL,.left = NULL,.right = NULL
    };
    tree->count = 1;
    tree->amount = 1;
    tree->head = tree->parts[0];
    tree->last = tree->parts[0];
    return 0;
  } else if(tree->count % tree->max_items_per_part == 0) { // make more space if lacking memory
    /* ... */
  }
  /*
  grab the next node (no gaps between them so going
  from the lowest address to the highest linearly,thus going to a new page once a while)
  */
  temp = ++tree->last;
  ++tree->count;
  while(1) {
    if(sfd > node->sfd) {
      if(node->right != NULL) {
        node = node->right;
      } else {
        *temp = (struct net_avl_node) { // a page fault
          .sfd = sfd,.parent = node,.right = NULL
        };
        node->right = temp;
        /* ... */
        break;
      }
    } else {
      if(node->left != NULL) {
        node = node->left;
      } else {
        *temp = (struct net_avl_node) { // a page fault
          .sfd = sfd,.right = NULL
        };
        node->left = temp;
        /* ... */
        break;
      }
    }
  }
  /* rebalancing */
  return 0;
}

我也在使用 -O3 -Wall -lpsapi -Wno-missing-braces -Wmissing-field-initializers -D_GNU_SOURCE 标志。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...