我是指令优化的新手.
我对一个简单的函数dotp进行了简单的分析,该函数用于获取两个浮点数组的点积.
C代码如下:
float dotp(
const float x[],
const float y[],
const short n
)
{
short i;
float suma;
suma = 0.0f;
for(i=0; i<n; i++)
{
suma += x[i] * y[i];
}
return suma;
}
Run Code Online (Sandbox Code Playgroud)
我用昂纳雾在网络上提供的测试框架testp.
在这种情况下使用的数组是对齐的:
int n = 2048;
float* z2 = (float*)_mm_malloc(sizeof(float)*n, 64);
char *mem = (char*)_mm_malloc(1<<18,4096);
char *a = mem;
char *b = a+n*sizeof(float);
char *c = b+n*sizeof(float);
float *x = (float*)a;
float *y = (float*)b;
float *z = (float*)c;
Run Code Online (Sandbox Code Playgroud)
然后我调用函数dotp,n = 2048,repeat …
我希望能够手动预测任意算术的长度(即没有分支或内存,尽管这也很好)x86-64汇编代码将采用特定的体系结构,考虑到指令重新排序,超标量,延迟,消费者价格指数等
什么/描述必须遵循的规则才能实现这一目标?
我想我已经找到了一些初步规则,但是我没有找到任何关于将任何示例代码分解为这个详细程度的引用,所以我不得不做一些猜测.(例如,英特尔优化手册甚至几乎没有提到指令重新排序.)
至少,我正在寻找(1)确认每条规则是正确的,或者是每条规则的正确陈述,以及(2)我可能忘记的任何规则的列表.
addps并且subps使用相同的功能) unit?我如何确定?).和:4此循环已经发出少于超标量宽度(通常)指令的数量.例如,请考虑以下示例代码(计算交叉产品):
shufps xmm3, xmm2, 210
shufps xmm0, xmm1, 201
shufps xmm2, xmm2, 201
mulps xmm0, xmm3
shufps xmm1, xmm1, 210
mulps xmm1, xmm2
subps xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
我试图预测Haswell的延迟看起来像这样:
; `mulps` Haswell latency=5, CPI=0.5
; `shufps` Haswell latency=1, CPI=1
; `subps` Haswell latency=3, CPI=1
shufps xmm3, xmm2, 210 ; cycle 1
shufps xmm0, xmm1, 201 ; cycle 2
shufps xmm2, xmm2, 201 ; …Run Code Online (Sandbox Code Playgroud) 我试图详细了解当分支预测错误时,skylake CPU管道的各个阶段中的指令会发生什么,以及从正确的分支目标开始执行指令的速度如何。
因此,让我们在这里将两个代码路径标记为红色(一个预测但未实际采用)和绿色(一个已预测但未预期)。所以问题是:1.在红色指令开始被丢弃之前,分支必须经过管道多远(以及在管道的哪个阶段被丢弃)?2.绿色指令(在分支到达的流水线阶段方面)多久可以开始执行?
我看过Agner Fogg的文档和许多讲义,但这些观点并不清楚。
x86 intel cpu-architecture speculative-execution branch-prediction
assembly ×2
c ×1
intel ×1
latency ×1
optimization ×1
pipeline ×1
sse ×1
superscalar ×1
x86 ×1
x86-64 ×1