如何解决将页面预取到 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 举报,一经查实,本站将立刻删除。