【发布时间】:2010-09-13 14:57:12
【问题描述】:
CPU 中的乱序执行意味着 CPU 可以重新排序指令以获得更好的性能,这意味着 CPU 必须进行一些非常漂亮的簿记等工作。还有其他处理器方法,例如超线程。
一些花哨的编译器在有限程度上理解指令的(不)相互关联性,并且会自动交错指令流(可能在比 CPU 看到的更长的窗口内)以更好地利用处理器。浮点和整数指令的故意编译时交错是另一个例子。
现在我有高度并行的任务。而且我通常有一个老化的单核 x86 处理器,没有超线程。
是否有一种直接的方法可以让我的“for”循环主体交错交错,以便一起完成两个(或多个)迭代? (这与我理解的“循环展开”略有不同。)
我的任务是通过一组指令运行的“虚拟机”,我将其简化为:
无效运行(int num){
for(int n=0;n所以执行轨迹可能如下所示:
data(1) insn(0) 解析
数据(1)insn(0)评估
数据(1) insn(1) 解析
...
数据(2)insn(1)评估
数据(2) insn(2) 解析
数据(2)insn(2)评估
现在,我希望能够显式地并行进行两次(或多次)迭代:
data(1) insn(0) 解析
data(2) insn(0) parse \ processor 可以做OOO,因为这两个流入
数据(1)insn(0)评估/
data(2) insn(0) eval \ OOO 机会也在这里
数据(1)insn(1)解析/
数据(2)insn(1)解析
我知道,从分析中(例如,将 Callgrind 与 --simulate-cache=yes 一起使用),解析是关于随机内存访问(缓存丢失),而 eval 是关于在寄存器中执行操作,然后将结果写回。每个步骤都有数千条指令长。因此,如果我可以一次将这两个步骤混合在一起进行两次迭代,那么处理器有望在解析步骤的缓存未命中发生时有一些事情要做......
是否有一些 C++ 模板疯狂来生成这种显式并行性?
当然,我自己可以在代码中进行交错 - 甚至是惊人的 - 但这会导致代码的可读性大大降低。如果我真的想要不可读,我可以去汇编!但是这种事情肯定有一些模式吗?
【问题讨论】:
-
我认为这个问题很有趣也很重要,但是让我觉得不好的是“现在我有高度并行的任务。而且我通常有一个老化的单核 x86 处理器,没有 hyper ——穿线。”如果您没有可并行化的 CPU,那为什么要这样做?
-
我相信混合“解析”和“在寄存器中执行操作”的想法根本不会带来任何加速,因为这是 CPU 供应商自己使用寄存器重命名等技术所做的事情, 存储转发。
-
在一个线程中混合两个 VM 的解析和执行 - 自从提出这个问题以来 - 到目前为止已经提高了 16%。但是我的混合是反复试验,所以我极有可能还没有接近可能的改进。我仍在寻找一种非意大利面的方式来组织代码
-
太棒了。测量总是正确的,因此我衷心承认我错了。我现在会尝试考虑一些可以帮助您的模板魔法(并不是说我会非常依赖我带来任何东西,但谁知道呢,也许我会遇到一些事情)
标签: c++ performance design-patterns