我在内存缓冲区中存储了30MB的字节数组。我想定期采样数组的10%。
我可以每10个字节采样一次:
或者我可以一次采样4个字节,每40个字节:
换句话说,我一次读取任意数量的字节,前提是所分析的字节占我总数据的10%,并且读取的大小均匀且间隔一定。
如果我不使用SSE等矢量化指令,那么读取此数据的性能如何取决于采样结构的大小?
x86和ARM之间的速度变化趋势如何?
是否有画线(例如:32字节+),之后增加采样结构的大小不会将性能提高超过百分之几?
鉴于总数据将无法容纳在缓存中,改变采样结构大小是否会根本改变性能?
最佳答案
在具有L
大小的高速缓存行的硬件上从一个非常长的字节数组中读取10%的数据时,当您从高速缓存行的对齐位置开始读取,一次读取L
字节,跳过以下9*L
字节时,将获得最佳性能,并从那时开始继续。这样可以最大程度地增加缓存命中次数,从而加快程序运行速度,因为您仅将数据的1/10加载到缓存中。
高速缓存行大小为64字节左右时,这会在示例中留下很大的空白,因此最终将使用一种每次读取较少字节的方法。
让我们看一下您拥有的两种方法,即一次4个字节与一次1个字节。假设L = 64。
第一种方法将具有六到七个命中缓存行,具体取决于第一个读取的“着陆”线在行内的距离。如果第一次读取是在前四个字节之内,那么您将获得六次点击;否则,您将获得5次点击。平均而言,每条缓存行有6.4次匹配(数学公式如下:四个“好”位置给我们六个命中,六个“不良”位置给我们五个命中;除以可能的初始位置总数(4 * 7 + 6 * 6)/ 10)。
第二种方法将使您每个高速缓存行命中四至八次命中-同样,这取决于第一次读取的位置。假设所有读取都在4字节边界对齐,那么从0到20(包括0和20)的位置开始读取,每行将有8个匹配项。在其他位置开始读取将使您每行点击四个。您有六个“好”位置(0、4、8、12、16和20)和四个“坏”位置(24、28、32和36),因此结果还是6.4,或(8 * 6 + 4 * 4)/ 10。
如您所见,两种方法之间的缓存利用率没有差异。这是有道理的,因为您永远不会跳过一行。仅当您可以跳过整个缓存行中有值(value)的内存时,您才能进行改进。
同样,假设高速缓存行的大小为64,并且您读取了10%的数据,则一次需要读取的最小字节总数是每70个字节中的7个字节(或更可能是每80个中的8个字节,因为8是更“对齐友好”的数字)。
关于c++ - 对齐的数据:速度取决于恒定数据读取时的相对采样大小和采样频率,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29350569/