当前位置: 首页 > 知识库问答 >
问题:

如何实现缓存友好的动态二叉树?

顾俊楚
2023-03-14

根据包括维基百科在内的几个来源,实现二叉树最常用的两种方法是:

  1. 每个节点显式保存其子节点的节点和指针(或引用)
  2. 子节点的位置由其父节点的索引隐式给定的数组

第二种方法在内存使用和引用的局部性方面明显优越。但是,如果希望以可能导致树不平衡的方式允许从树中插入和删除,则可能会导致问题。这是因为这种设计的内存使用是树深度的指数函数。

假设您希望支持这种插入和删除。如何实现树,使树遍历充分利用CPU缓存。

我在考虑为节点创建一个对象池,并在数组中分配它们。这样节点就会靠近在一起-

但是,如果节点的大小与缓存线的大小相同,这有意义吗?

如果L1行大小为64字节,并且访问std::vector的第一个成员


共有2个答案

邹博明
2023-03-14

使用块分配器。

您有一个或几个连续的内存“池”,可以从中分配固定大小的块。它被实现为一个链表。因此,分配很简单

answer = head, 
head = head->next, 
return answer; 

释放只是简单的

tofree->next = head;
head = tofree;

如果您允许多个池,您当然需要编写代码来确定池,这会增加一点复杂性,但不会太多。它本质上是一个简单的内存分配系统。由于所有池成员在内存中靠得很近,因此可以在小树上获得良好的高速缓存一致性。对于大树,你必须更聪明一点。

暴才俊
2023-03-14

除非您正在研究如何改进缓存访问模式的二叉树,否则我觉得这是一个XY问题—您试图解决的问题是什么?为什么你认为二叉树是解决你问题的最佳算法?预期的工作集大小是多少?

如果您正在寻找一个通用的关联存储,有多个缓存友好(其他关键字:缓存高效,缓存健忘)算法,如朱迪数组,其中有一个广泛的解释PDF。

如果您的工作集大小足够小,并且您只需要有序的项目集,一个简单的有序数组可能就足够了,这可能会带来另一个性能优势——分支预测。

最后,为了找出最适合您的用例的方法,您需要尝试并度量不同的方法。

 类似资料:
  • 下面是我使用的代码片段: 问:有人能告诉我我的错误是什么吗?为什么我会得到这个结果?

  • 我正在开发一个Web应用程序,其中后端在Spring引导中开发,消耗公共API中返回JSON中数据的数据。搜索是通过术语、全文(像谷歌)完成的,后端从应用程序前端接收用户的查询,用户的查询反过来搜索公共应用编程接口,等待响应,处理信息并将其发送到前端。我想在后端Spring Boot中实现缓存系统。基本上,在Spring引导调用API发布并等待响应之前,它会检查键/值系统是否已经在过去完成了搜索,

  • 我正在尝试将基于列表的树实现转换为基于数组的实现,其中父项位于第i个索引,左子项位于第2个索引,右子项位于第2i个索引。由于某种原因,转换会导致具有更大数量节点的树的数据丢失。我想知道在实现此功能时需要检查哪些所有边界条件。谢谢!

  • 我正在尝试创建一个无序二叉树。我们如何在无序二叉树中插入Treenode?应该是什么逻辑? 这里的插入是指将节点作为叶子插入。比如,如果我从根节点开始,然后遍历到右边的节点,现在我应该在哪里插入节点。 如果有人引用了UNORDERED二叉树[Not BST]实现,请提供。

  • 本文向大家介绍JDK动态代理之WeakCache缓存的实现机制,包括了JDK动态代理之WeakCache缓存的实现机制的使用技巧和注意事项,需要的朋友参考一下 上一篇我们分析了Proxy类的内部是怎样产生代理类的,我们看到了Proxy内部用到了缓存机制,如果根据提供的类加载器和接口数组能在缓存中找到代理类就直接返回该代理类,否则会调用ProxyClassFactory工厂去生成代理类。这里用到的缓

  • 背景: 项目里使用了Guava本地缓存,缓存了数据库的一部分数据,项目使用K8S部署,大概有10台左右的机器。当数据库更新时,希望所有机器的缓存同步更新。目前采用的是canal监听binlog + 刷入kafka。基于此场景,所以项目使用了广播模式来消费kafak的消息。 问题:由于机器的数目会基于整体压力动态变化,并不是固定数量,所以我们在项目里并没有写死消费者组ID,而是采用了随机数目的方式。