对齐数据:速度取决于相对采样大小和恒定数据读取的采样频率

时间:2015-03-30 15:46:15

标签: c++ performance memory-alignment

我有一个30MB的字节数组存储在内存缓冲区中。我想以周期性方式对10%的数组进行采样。

我可以每隔10个字节采样一次:

  

... xoooooooooxoooooooooxoooooooooxoooooooooxoooooooooxooooooooox

或者我可以每40个字节一次采样4个字节:

  

... xxxxooooooooooooooooooooooooooooooooooooxxxxoooooooooooooooooooooooooooooooooooo

换句话说,我一次读取任意数量的字节,只要分析的字节数占总数据的10%,并且我的读数大小均匀且间隔均匀。

如果我不使用像SSE这样的矢量化指令,那么读取这些数据的性能如何取决于采样结构的大小?

x86和ARM之间的速度有何不同?

是否有绘图线(比方说:32字节+)之后增加采样结构的大小并不能提高性能超过百分之几?

鉴于总数据不适合缓存,改变采样结构大小是否会改变性能?

2 个答案:

答案 0 :(得分:4)

当从具有大小为L的高速缓存行的硬件上读取来自非常长的字节数组的10%的数据时,当读取从高速缓存行的对齐开始时,将获得最大性能,读取{{1}每次调用字节,跳过以下L个字节,然后从该点开始继续。这样可以最大限度地提高缓存命中次数,从而加快程序运行速度,因为只将1/10的数据加载到缓存中。

如果缓存行大小为64字节,则样本中会留下相当大的间隙,因此您最终会使用一次读取较少字节的方法。

让我们看看你有两种方法,即一次4个字节,一次一个字节。我们假设L = 64。

第一种方法将有6到7次命中高速缓存行,具体取决于第一次读取“搁置”行内部的距离。如果第一次读取在最初的四个字节内,则会得到六次点击;否则,你会得到五次安打。平均而言,每个缓存行将有6.4次点击(数学如下:四个“好”位置给我们六个点击,六个“坏”位置给我们五个点击;除以可能的初始位置总数(4 * 7 + 6 * 6)/ 10)。

第二种方法将为每个缓存行提供四到八次点击 - 再次,取决于第一次读取的位置。假设所有读取都在4字节边界处对齐,从0到20(包括0和20)开始读取将为每行提供8次点击。在其他位置开始阅读将为您提供每行四次点击。你有6个“好”位置(0,4,8,12,16和20)和4个“坏”位置(24,28,32和36),所以结果再次是6.4,或者(8 * 6) + 4 * 4)/ 10。

如您所见,两种方法之间的缓存利用率没有差异。这是有道理的,因为你永远不会跳过一条线。只有当你可以跳过整个缓存行的内存时,你才能做出改进。

同样,假设高速缓存行的大小为64并且您读取10%的数据,那么您一次需要读取的最小整数字节数是每70个字节中的7个字节(或者更可能是每80个字节中有8个字节) ,因为8更“对齐友好”数字)。

答案 1 :(得分:1)

这太宽泛了,但我会提出一些建议。

从端口采样

通常,从端口采样与存储器相关的时序相关性更高。例如,我们使用ISR每1ms读取一次ADC。数据存储在一个数组中,然后发送到平滑算法。

采样文件

从文件中采样的最佳方法是将尽可能多的数据传输到缓冲区中,然后从缓冲区中采样。

采样,每N个字节中的一个字节就像读取2D矩阵一样。处理器使用指针和偏移量(在您的情况下为10)。这个负载通常是一条指令。因此循环将指针递增10.如果数据不能适应缓存,则处理器将重新加载缓存。如果您可以将周期设计为缓存行大小的倍数,则程序执行速度会更快。

你最大的瓶颈是从文件中读取。从文件读取的最佳方法是以最少的请求读取大多数数据。还要保持硬盘旋转。与保持驱动器旋转相比,启动停止驱动器的开销很高。

其他方法

您可以使用DMA读取文件并在读取给定数量的字节后中断处理器。

多线程可能有助于从文件中读取数据。

效果

性能取决于分析(即测量)。至于ARM和x86之间的区别,您将不得不进行测量。由于进入处理器的时钟速率不同以及处理器如何配置为使用时钟速率,因此差异很大。

真正回答性能问题的唯一方法是通过分析和分析数据来获取数据。