1

我正在尝试使用 masm32 程序集从主内存中读取数据,为了做到这一点,我创建了(如先前在我的另一个问题的答案中所建议的那样)一个数组,该数组将包含非常分离的内存位置(以避免从缓存)。我已经设法创建了数组并让它被读取,但是,我有一个问题。我已经做过并测试过的这个数组正在使用我给它的数据(即数字)并且一切正常。但是我需要内存位置,但我在任何地方都找不到地图或对这些位置的引用。我的意思是我需要类似的东西:

my_arr db 5, 2, 8, 9, 1, 7, 3, 0, 4, 6

但我应该使用相应的内存位置保留字而不是使用数字。但我找不到它们 =( 甚至不知道还要寻找什么。


编辑

让我检查一下是否正确,然后您告诉我可以(而不是使用数组,而是使用变量之间的所有空间来强制从主存储器读取,对吗?

4

2 回答 2

0

正如您所说,这是一个(连续)字节数组:

my_arr db 5, 2, 8, 9, 1, 7, 3, 0, 4, 6

这是一个占用 10 MB 的变量(相对于 CPU 缓存来说很大):

wasted_space BYTE 10485760 DUP(?)

这里有几个变量,它们之间有很多浪费的空间:

my_var_1 db 5
spacer_1 BYTE 10485760 DUP(?)
my_var_2 db 2
spacer_2 BYTE 10485760 DUP(?)
my_var_3 db 8
spacer_3 BYTE 10485760 DUP(?)
my_var_4 db 9
spacer_4 BYTE 10485760 DUP(?)
my_var_5 db 1
spacer_5 BYTE 10485760 DUP(?)
my_var_6 db 7
spacer_6 BYTE 10485760 DUP(?)
my_var_7 db 3
spacer_7 BYTE 10485760 DUP(?)
my_var_8 db 0
spacer_8 BYTE 10485760 DUP(?)
my_var_9 db 4
spacer_8 BYTE 10485760 DUP(?)
my_var_10 db 6

这(在数据段中创建变量)是获取一些数据内存地址的一种方法(变量不包含地址......相反,变量位于地址处)。

获取内存地址的另一种方法是调用 O/S API,它从堆中分配内存并返回分配的内存的地址,例如 HeapAlloc 或 VirtualAlloc API。


我不知道你为什么在 ASM 中这样做(学习汇编除外)。如果要学习缓存,我原以为您也可以使用 C 来做到这一点(而且更容易)。

无论如何,我对缓存很好奇:多少空间足以导致缓存未命中?需要多少个不同的变量才能开始导致未命中(假设缓存是拆分的,因此可以包含多个(但只有少数)宽间距的内存缓存)?

显然,多年来,它(缓存)已成为一个复杂的主题。http://lwn.net/Articles/252125/是一篇链接自维基百科的文章。本文包括一些图表,例如图 3.11: Sequential Read for Multiple Sizes

于 2009-02-15T01:13:53.987 回答
0

汇编中的间接内存访问

要将数组中的字节视为内存地址,您需要将它们加载到可用作基地址的寄存器中,然后访问该寄存器指向的内存:

MOV AX, [MY_ARR+3]  ; Element 3 in array, that is 9
MOV BX, [AX]        ; Read from that address

关于缓存

请注意,您的缓存可能比该数组覆盖的内存地址范围大得多,因此所有内容都适合缓存。

此外,请考虑您的缓存可能是关联的,这意味着如果相距很远的地址碰巧不在同一(完整)缓存行上,则它们可以一起放入缓存中。

要真正用完缓存并保证您必须直接访问内存,您应该(在循环中)访问一组比缓存更大的连续内存位置。即创建一个与缓存一样大的数组。还要考虑到可能有多层缓存(L1、L2,可能是 L3 甚至更多),所以你需要多大取决于你想要溢出的缓存。


我用 C 语言编写了一个程序来计时内存和缓存访问一次,并通过一些统计计算和补偿时间测量开销(在如此短的时间范围内是不可忽略的),得到了非常准确的结果(可能是通过运行更长时间的测试并等待标准偏差下降来获得所需的准确度)。

然而,我的程序并不是最有效的方法,并且也没有暗示太多关于缓存的关联性(我必须根据配色方案的知识单独测量)。然而,在Larry McVoy 和 Carl Staelin 的 SIGMETRICS 2005 工作中,两者都以相对独立于架构的方式相当有效地完成了一些深思熟虑的技巧。

于 2009-02-15T06:37:41.730 回答