从用户空间访问ARM PLE(预加载引擎)(或如何获得全带宽内存访问)

时间:2016-03-02 14:31:41

标签: linux caching optimization arm kernel

我在不同的地方问过这个问题,我仍然试图得到任何答案。如果你遇到它,请原谅交叉发布。

这个问题归结为是否可以在ARM Cortex A9上以全速顺序访问主存储器,并且对我提出的方法存在特定问题。

我正在研究在667 MHz Cortex A9(在Xilinx Zynq中)运行的一些性能关键数字代码,这些代码当前是缓存限制的。我可以在小型数据集(~530 MFlops)上实现每次内存访问〜1次氖倍增,当数据大小变大时(在极限内约为180MFlops)下降到更低。这是在带有GCC堆栈的ARM Linux上。

上面的180个MFlops图是PLD指令(这肯定有帮助),但我仍远不及主存储器的理论存储器带宽(DDR2 @ 533MHz)。鉴于问题基本上是在先验完全定义的顺序内存访问上运行,我想知道是否可以使用L2预加载引擎加快速度。

现在,我已经尝试了一些,编写了一个小的内核驱动程序,它翻转了PLEUAR寄存器位,以便用户空间访问PLE(以及在PLEPCR寄存器中摆弄一点以减少PLE操作之间的循环) ,然后执行PLE操作(类似MCRR p15, 0, %[vect_addr], %[vect_config], c11;)。

从中可以看出各种各样的事情:

  1. 该程序在大约20%的时间内成功运行,其余时间在第一次尝试设置PLE时几乎立即产生“非法指令”。
  2. 运行时间不受影响。如果这是预期的,我很有兴趣知道是否可以对以内存带宽访问的数据进行操作。
  3. 我可以监视(16个长度)FIFO,并观察它在空间中随着指令的添加而减少,然后恢复为空。
  4. 我的观察结果表明我没有做我认为我正在做的事情,或者至少有些事情妨碍了我做我想做的事情。

    我错过了一些基本的东西吗?我是否正在遍布内核受到严密保护的空间?

    与正在运行的进程相比,PLE查看的虚拟地址是否不同?

    为什么非法指令会发生?

1 个答案:

答案 0 :(得分:1)

Xilinx可靠地告诉我,Zynq的所有模型都有双核Cortex-A9,所以我猜你正在运行SMP Linux和你的内核模块并没有考虑到这一点。除非您使用其中一个on_each_cpu*来对每个核心执行启用操作,否则您需要针对调度程序设置自己的俄罗斯轮盘游戏。另请注意,如果您有cpuidle或任何其他电源/热管理,核心可能失去状态,这将增加乐趣,因为无法保证空闲/热插拔代码将带来回到他们干涉的状态。

现在,尽管如此,预加载引擎是特定于某些Cortex-A9配置的疯狂事情,没有人使用,特别是在Linux中。我不确定它的原始设计意图,但我怀疑它更多地与从ACP挂起的GPU或其他设备相比,而不是核心本身,它们完全能够管理它们自己的预取。它也无法解决你真正的问题:DRAM和L2之间的世界上所有带宽仍然不能阻止你在L1丢失,它只会让它受到更少的伤害。在较旧的内核上实现最大处理带宽,就是要以适当的数量展开你的循环,并微调你的PLD以寻找让L1尽可能热的最佳点 - 这显然取决于大量特定于系统的因素,但通常可以达到预先约2-4个缓存行的预取距离。