Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 最小化页面错误(和TLB错误),同时;“步行”;大图_Performance_Graph_X86_Garbage Collection_Page Fault - Fatal编程技术网

Performance 最小化页面错误(和TLB错误),同时;“步行”;大图

Performance 最小化页面错误(和TLB错误),同时;“步行”;大图,performance,graph,x86,garbage-collection,page-fault,Performance,Graph,X86,Garbage Collection,Page Fault,问题(考虑GC的标记阶段) 我有一个我需要行走的“对象”图,访问所有对象 如果访问过每个对象,我可以将其存储在其中 所有对象都存储在内存中,并使用普通指针链接在一起 对象的大小不尽相同 有时系统中没有足够的ram来同时保存内存中的所有对象,我希望避免“页面抖动” 我还希望避免TLB故障 其他时候,内存已经足够了 我不介意编写低级代码 我不介意windows和linux使用不同的代码 代码必须在“用户空间”中运行,而不需要任何标准权限 我不在乎访问中节点的顺序 我将问一些关于可能解决方案的更详

问题(考虑GC的标记阶段)

  • 我有一个我需要行走的“对象”图,访问所有对象
  • 如果访问过每个对象,我可以将其存储在其中
  • 所有对象都存储在内存中,并使用普通指针链接在一起
  • 对象的大小不尽相同
  • 有时系统中没有足够的ram来同时保存内存中的所有对象,我希望避免“页面抖动”
  • 我还希望避免TLB故障
  • 其他时候,内存已经足够了
  • 我不介意编写低级代码
  • 我不介意windows和linux使用不同的代码
  • 代码必须在“用户空间”中运行,而不需要任何标准权限
  • 我不在乎访问中节点的顺序

我将问一些关于可能解决方案的更详细问题,并链接回这些问题。

这些是我对可能解决方案的第一个想法,它们显然不是最优的。如果有人发布更好的答案,我将删除此答案

基本方法:

  • 假设我们有一个
    Set nodesToVisit
    ,其中包含我们尚未访问的所有节点

  • 我们从
    nodesToVisit
    中一次删除一个项目

    • 如果在我们将所有“指向其他节点的指针”添加到nodesToVisit之前它还没有被访问过
改进

但我们显然可以做得更好,根据地址对nodesToVisit进行排序,这样我们就更有可能访问最近访问过的页面中包含的节点。这可能很简单,只需拥有第二个
Set nodesToVisitLater
,然后将任何地址距离当前节点很远的节点放入其中

或者,我们可以跳过不驻留在内存中的页面中包含的任何节点,在访问了当前内存中的所有节点之后访问这些节点

(该“集合”可能只是一个堆栈,因为多次访问一个节点是“无操作”)


似乎有关联,但我还没有读过。
这些是我对可能的解决方案的最初想法,它们显然不是最优的。如果有人发布更好的答案,我将删除此答案

基本方法:

  • 假设我们有一个
    Set nodesToVisit
    ,其中包含我们尚未访问的所有节点

  • 我们从
    nodesToVisit
    中一次删除一个项目

    • 如果在我们将所有“指向其他节点的指针”添加到nodesToVisit之前它还没有被访问过
改进

但我们显然可以做得更好,根据地址对nodesToVisit进行排序,这样我们就更有可能访问最近访问过的页面中包含的节点。这可能很简单,只需拥有第二个
Set nodesToVisitLater
,然后将任何地址距离当前节点很远的节点放入其中

或者,我们可以跳过不驻留在内存中的页面中包含的任何节点,在访问了当前内存中的所有节点之后访问这些节点

(该“集合”可能只是一个堆栈,因为多次访问一个节点是“无操作”)


似乎有关联,但我还没有读过。
页面错误不一定是坏的,只要它们不会阻碍您的进度

这意味着,如果您有一个节点
node*p
,其中有两个候选后续节点
p->left
p->right
,则可以选择最近的节点(根据
(char*)p-(char*)p->next
)并预取另一个节点(例如,使用)

效率如何无法预测;这在很大程度上取决于图形拓扑。但当您有足够的RAM时,预取实际上是免费的


靠近中央处理器的地方有一个。同样的想法,不同的存储

页面错误并不一定是坏的,只要它们不会阻碍您的进度

这意味着,如果您有一个节点
node*p
,其中有两个候选后续节点
p->left
p->right
,则可以选择最近的节点(根据
(char*)p-(char*)p->next
)并预取另一个节点(例如,使用)

效率如何无法预测;这在很大程度上取决于图形拓扑。但当您有足够的RAM时,预取实际上是免费的


靠近中央处理器的地方有一个。同样的想法,不同的存储对充满“热”数据的地址范围使用2M大页面,内核无法有效地交换任何/多个4k数据块。这将减少TLB未命中,但如果一个大页面中有任何4k块不是热的,则会消耗额外的物理内存

Linux对匿名页面()透明地执行此操作,但您可以在您认为值得的页面上使用此操作,以鼓励内核对物理内存进行碎片整理,即使这不是
/sys/kernel/mm/transparent\u hugepage/defrag
中的默认值。(您可以查看
/proc/PID/smaps
,查看有多少透明的hugepages用于任何给定的映射。)


根据您在回答中发布的内容:一组有序的
nodesToVisit
将为您提供最多的位置信息,但维护成本可能太高。同一个64字节缓存线内的多个访问要比从三级缓存中移出并再次从DRAM返回后的访问便宜得多

如果你的集合中有很多地址要访问,那么在2M个存储桶中进行一次基数排序将使你在一个大页面内获得位置信息。2M也比L3缓存大小小,因此当访问同一缓存线中的多个对象时,可能会得到一些缓存命中,即使您没有背对背地命中它们

根据你的布景有多大,扔吧