问题标签 [memory-access]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
483 浏览

java - 数据对齐与缓存局部性

从内存中,数据只能以体系结构的自然字长读取。例如,在 32 位系统上,数据以 4 字节块的形式从内存中读取。如果将 2 字节或 1 字节的值添加到内存中,它们的读取仍需要访问 4 字节的字。(对于 2 字节值,如果值存储在字边界上,则可能需要两次 4 字节访问。)

因此,当需要访问单个单词时,访问单个值是最快的,并且需要最少的额外工作(例如掩码)。如果我是正确的,这就是虚拟机(例如JVMAndroid 的 DalvikObject )在实例中以 4 字节边界布置成员变量的原因。

另一个概念是缓存友好性,即局部性(例如L1、L2)。如果许多值必须在彼此之后直接遍历/处理,则将它们彼此靠近存储(理想情况下,在连续块中)是有益的。这是空间局部性。如果这是不可能的,那么至少对相同值的操作应该在相同的时间段内完成(时间局部性——即在对其执行操作时,该值很有可能保留在缓存中)。

据我所知,上述两个概念在某些情况下可能是“矛盾的”,它们之间的选择取决于它们的使用场景。例如,较少量的连续数据比大量(微不足道的)数据对缓存更友好,但如果某些数据通常需要随机访问,则字对齐(但更大)结构可能是有益的——除非整个结构适合缓存。因此,我认为,是否应该首选局部性(~arrays)或对齐优势取决于如何操纵这些值

有一个场景对我来说很有趣:让我们假设一个寻路算法将输入图(其他辅助结构)作为数组接收。(它的大部分输入数组存储的值都是 <= 32767。)

寻路算法对数组执行非常多的随机访问(在几个循环中)。从这个意义上说,int[]输入数据(在 Android/ARM 上)可能需要一个,因为访问时这些值将位于字边界上。(另一方面,如果需要顺序遍历,则建议使用较小的数据类型——尤其是对于大型数组——因为缓存友好的可能性更高。)

但是,如果(随机访问的)输入数据在指定为 a 时适合 L1/L2 short[],但如果指定为 则不适合int[]怎么办?在这种情况下,int[]随机访问的 4 字节对齐的优势是否会被 的缓存友好性所抵消short[]

当然,在具体应用中,我会进行测量以进行比较。然而,这不一定能回答上述问题。

0 投票
4 回答
2638 浏览

caching - 缓存和TLB命中率的关系

下面是一个操作系统(Gate 2003 OS)的MMU的描述:

处理器使用 2 级页表进行虚拟到物理地址的转换。两个级别的页表都存储在主存储器中。虚拟地址和物理地址都是 32 位宽。存储器是字节可寻址的。对于虚拟地址到物理地址的转换,虚拟地址的 10 个最高有效位用作第一级页表的索引,而接下来的 10 位用作第二级页表的索引。虚拟地址的 12 个最低有效位用作页面内的偏移量。假设两级页表中的页表项都是 4 个字节宽。此外,处理器具有翻译后备缓冲区(TLB),命中率高达 96%。TLB 缓存最近使用的虚拟页号和相应的物理页号。该处理器还有一个物理寻址的高速缓存,命中率为 90%。主存访问时间为10ns,缓存访问时间为1ns,TLB访问时间也是1ns。

问题是:

命中率 90% 的缓存和命中率 96% 的 TLB 有什么关系?操作系统首先检查哪里:数据还是指令?

0 投票
1 回答
239 浏览

java - java - 如何在运行时访问Java程序的内存变量?

我在eclipse中运行一个java爬虫程序。我没有启用调试器。

爬行完成后,我正在打印一些变量。但是爬虫需要很长时间才能完成,所以我不知道什么时候会打印这些变量。

我想在爬虫运行时访问这些变量,我不想停止它,因为它已经运行了一段时间。我如何访问这些变量?谢谢

0 投票
1 回答
198 浏览

exception - EXC_BAD_ACCESS 记录在哪里?

在我自己的开发(Mac、iOS)中,最常见的调试错误之一是 EXC_BAD_ACCESS。尽管它很常见,但它的起源和确切含义仍然是神秘的。谷歌列出了许多出现的错误,但我能找到的唯一解释是非正式的和不完整的。

我知道这个异常(如果这是正确的术语)意味着代码试图访问它没有读取和/或写入权限的地址 - 例如,空地址或进程的地址空间。但这是基于我之前在虚拟内存和受保护内存系统方面的经验的直观解释。我从来没有在任何地方看到过 EXC_BAD_ACCESS 的文档,实际上我不确定“谁”向我发送了这个异常——CPU、Mac OS、UNIX、运行时、调试器?——所以我不知道该问谁(那个是,要查阅哪类文档)。例如,我想知道与异常一起列出的“代码”是什么意思。或者另一个例子:还有哪些其他类的类似异常(大概也标有“EXC_”

我在哪里可以从权威来源找到 EXC_BAD_ACCESS、其代码和一般语义的解释?什么权威来源——实际上是谁在检测和抛出异常?

0 投票
5 回答
12975 浏览

pointers - 在 64 位指针中使用额外的 16 位

我读到64 位机器实际上只使用 48 位地址(具体来说,我使用的是 Intel Core i7)。

我希望额外的 16 位(位 48-63)与地址无关,并且会被忽略。但是当我尝试访问这样的地址时,我得到了一个信号EXC_BAD_ACCESS

我的代码是:

为什么会这样?有没有办法使用这 16 位?

这可用于构建对缓存更友好的链表。代替使用 8 个字节用于下一个 ptr 和 8 个字节用于键(由于对齐限制),键可以嵌入到指针中。

0 投票
1 回答
1979 浏览

memory - 双字节内存访问粒度

我正在尝试学习内存对齐,诚然没有太大的成功。我正在使用这个文章。

有人可以向我解释一下这段摘录在双字节内存访问粒度部分的含义:

但是,请注意从地址 1 读取时会发生什么。因为地址不是均匀地落在处理器的内存访问边界上,所以处理器有额外的工作要做。这样的地址称为未对齐地址。由于地址 1 未对齐,因此具有两字节粒度的处理器必须执行额外的内存访问,从而减慢操作速度。

为什么要按顺序进行另一个内存访问?内存访问边界是什么意思,甚至在内存访问边界上?

我对 CPU 的了解非常有限,因为我只熟悉高级编程(Objective-C 和 C++)。任何帮助是极大的赞赏!

谢谢!

0 投票
3 回答
3580 浏览

c - 在 C 中访问内存地址的内容

几个小时以来,我一直试图弄清楚这一点,这让我有点发疯。执行程序时不断出现分段错误,我该如何解决?我也收到警告“尝试从不同大小的整数中指向指针”,但是当我使用强制转换 (int *) 时,我仍然收到警告。请帮助...这是代码:


0 投票
1 回答
3757 浏览

optimization - 如何为邻居访问优化 OpenCL 代码?

编辑:建议的解决方案结果添加在问题的末尾。

我开始使用 OpenCL 进行编程,并且我已经为我的问题创建了一个幼稚的实现。

理论是:我有一个元素的 3D 网格,其中每个元素都有一堆信息(大约 200 字节)。每一步,每个元素都会访问它的邻居信息并积累这些信息以准备更新自己。之后有一个步骤,每个元素使用之前收集的信息进行自我更新。这个过程是迭代执行的。

我的 OpenCL 实现是:我创建一个 1 维 OpenCL 缓冲区,用代表元素的结构填充它,这些元素有一个“int neighbors 6 ”,我将邻居的索引存储在缓冲区中。我启动了一个内核,它会咨询邻居并将它们的信息累积到此步骤中未咨询的元素变量中,然后我启动另一个使用此变量更新元素的内核。这些内核仅使用 __global 变量。

示例代码:

现在,我的 OpenCL 实现与我的 C++ 实现所花费的时间基本相同。

所以,问题是:您(专家:P)将如何解决这个问题?我已阅读有关 3D 图像的信息,以存储信息并通过将 NDRange 更改为 3D 来更改邻域访问模式。另外,我已经阅读了 __local memory,首先加载工作组中的所有邻域,与屏障同步然后使用它们,从而减少对内存的访问。

您能否给我一些提示来优化我所描述的流程,如果可能的话,给我一些片段吗?

编辑: Huseyin Tugrul提出的第三和第五个优化已经在代码中。正如这里提到的,要使结构正常运行,它们需要满足一些限制,因此值得理解以避免头痛。

编辑 1 :应用Huseyin Tugrul提出的第七个优化,性能从 7 fps 提高到 60 fps。在更一般的实验中,性能增益约为 x8。

编辑 2 :应用Huseyin Tugrul提出的第一个优化,性能提高了大约 x1.2。我认为真正的收益更高,但由于另一个尚未解决的瓶颈而隐藏。

编辑 3 :应用Huseyin Tugrul提出的第 8 和第 9 优化并没有改变性能,因为缺乏利用这些优化的重要代码,尽管值得在其他内核中尝试。

编辑 4:将不变参数(例如 n_elements 或 workgroupsize)作为 #DEFINEs 而不是内核参数传递给内核,如此处所述提高了 x1.33 左右的性能。正如文档中所解释的,这是因为编译器在编译时知道变量时可以进行积极的优化。

编辑 5 :应用Huseyin Tugrul提出的第二个优化,但使用每个邻居 1 位并使用按位运算来检查邻居是否存在(因此,如果邻居 & 1 != 0,则存在顶部邻居,如果邻居 & 2 != 0,机器人邻居存在,如果邻居 & 4 != 0,右邻居存在,等等),性能提高了 x1.11 倍。我认为这主要是因为数据传输减少,因为数据移动一直是我的瓶颈。很快我将尝试摆脱用于向我的结构添加填充的虚拟变量。

编辑 6:通过消除我正在使用的结构,并为每个属性创建单独的缓冲区,我消除了填充变量,节省了空间,并且能够优化全局内存访问和本地内存分配。性能提高了 x1.25 倍,非常好。值得这样做,尽管程序复杂且不可读。

0 投票
1 回答
410 浏览

opengl - OpenGL vbo结构

我正在学习 opengl 并使用 VBO 的示例,它由 GL.DrawElements() 使用的颜色数组、顶点数组、法线数组和索引数组组成,结构看起来像(一个点表示下一个元素/项目):

我需要将它们用作:

因为我将 opencl 内核的缓冲区数据用作 cl-gl-interop 并且第一种类型的结构进行跨步内存访问,这会降低主内存访问的性能,因为我只使用每个元素/项目的一个组件,例如仅“x”或只有“r”。但第二种结构是平等地使用所有内存库,适合我的需要。这种结构是否可用/适合opengl绘图操作?

0 投票
1 回答
227 浏览

performance - 机器代码生成、内存访问/寄存器操作模式和性能?

我很难为这个问题制定一个标题,而且我认为我做得不是很好,所以如果有人有更好的想法,编辑按钮就是你的了。

考虑到内存操作在绝对最佳情况下花费 3-4 个周期,甚至可能更多,并且读取比内存总线“更窄”的数据是次优的,当前生成的汇编语言结构不是次优的也?

寄存器操作花费的时间要少得多,所以为什么程序集不获取在表达式之前评估表达式所需的所有数据并快速执行它,从而减少线程切换并允许处理器执行其他线程。

最后,有 15 个 CPU 使用周期。

使用了 11 个周期,提高了 25%。此外,实际的 CPU 只忙了 3 个周期,因为内存由专用的片上硬件控制器获取,并且空闲时间更长。

我想 CPU 可以在等待第一个“示例”中的数据时安排其他代码执行,但是对于更短的窗口,并且切换上下文的周期惩罚几乎不值得,我认为第二个方法虽然更需要寄存器,但应该会带来更好的整体 CPU 性能。毕竟,现代处理器都至少有 16 个寄存器,即使是当前这一代新的移动设备 ARM 芯片也有 32 个寄存器。那为什么要这么保守呢?也许编译器还停留在 8 台寄存器机器的时代?

这个假设是否成立,或者当前的 CPU 架构可能不是为了受益于这种机制而设计的?我假设当 CPU 等待数据时,它可以执行其他代码,特别是考虑到大多数现代处理器都是无序的,所以最后,最坏的情况是,你会浪费同样的时间来获取数据,但是拥有所有数据将使代码片段执行得更快,从而使处理器停顿更短的时间。