深入理解计算机系统(第二版) 家庭作业 第五章

这一章我觉得问题还是比较多的,也不是特别理解CPE的计算。
如果对题目有什么其他见解,欢迎大家一起讨论。

5.15
A.
深入理解计算机系统(第二版) 家庭作业 第五章_第1张图片
深入理解计算机系统(第二版) 家庭作业 第五章_第2张图片
关键路径是%xmm1更新路径上的加法。

B. CPE下界是浮点加法的延迟。
C. 两个load操作的吞吐量界限。(我觉得是2.00)
D. 因为乘法不在关键路径上,乘法也是流水线执行的,其限制因素为吞吐量界限。整个程序的限制因素为最后的浮点数加法的延迟,这个延迟对float和double都是3.00。


书上之前说关键路径,现在其实可以再仔细分析一下(以下属于个人分析):
把执行指令写出了就明了了。
以整数为例:
相同底色表示这些指令在一个循环内执行,以及同一个循环内的初始值:
所以我觉得整数的时候CPE是2.00,可是为什么是3.00呢?
浮点数的话,延迟是3.00没问题。


时间线 xmm1_add单元 xmm1 mul单元发射 load单元发射 rdx_add单元 rdx的值
1
0
load1  add +0
2
0
load2
+1
3


load1 add +1
4


load2
+2
5


load1 add +2
6

mul
(load延迟4)
load2 ...
7


...

8
0 mul


9 add
整数mul
延迟为3
0



10
added
整数加法
延迟为1
mul


11 add




12
added





5.16

void inner4(vec_ptr u, vec_ptr v, data_t *dest)
{
    long int i;
    int length = vec_length(u);
    data_t *udata = get_vec_start(u);
    data_t *vdata = get_vec_start(v);
    data_t sum = (data_t) 0;
    int limit = length - 2;
    for (i = 0; i < limit; i++) {
        sum = sum + udata[i] * vdata[i];
        sum = sum + udata[i+1] * vdata[i+1];
        sum = sum + udata[i+2] * vdata[i+2];
    }
    
    for(; i         sum = sum + udata[i] * vdata[i];
    *dest = sum;
}

A. 因为load吞吐量为1.00,每计算一个值需要两次load,所以CPE不可能低于2.00。
B. 关键路径上仍然有N个浮点加法,所以循环展开并没有改变

5.17

A. load执行单元的吞吐量
B. IA32可用寄存器实际只有6个,而三路展开需要i, limit, udata, vdata,以及存储udata[i], vdata[i]的寄存器,所以肯定有些循环变量会溢出到寄存器,这会影响效率。(至于为什么是2.67以及为什么四路展开的整数会是2.33,还不是很清楚)。

5.18
void inner4(vec_ptr u, vec_ptr v, data_t *dest)
{
    long int i;
    int length = vec_length(u);
    data_t *udata = get_vec_start(u);
    data_t *vdata = get_vec_start(v);
    data_t sum = (data_t) 0;
    int limit = length - 2;
    for (i = 0; i < limit; i++) {
        int x1 = udata[i] * vdata[i];
        int x2 = udata[i+1] * vdata[i+1];
        int x3 = udata[i+2] * vdata[i+2];
        sum = sum + (x1 + x2 + x3);
    }
    for(; i         sum = sum + udata[i] * vdata[i];
    *dest = sum;
}


5.19
void *optimized_memset(void *s, int c, size_t n)
{
    unsigned int K = sizeof(unsigned long);
    unsigned char *schar = (unsigned char*)s;
    unsigned long *lchar;
    unsigned long fill = 0;
    int i = 0;
    for(i = 0; i < K; i++)
        fill += (c&0xff) << (i<<3);

    // n如果是个负数,会变成一个很大的正数,这应该不需要处理吧?
    // size_t应该是unsigned int,n应该不可能是
    //一般K都是2的整数次幂,也可以用schar&(K-1)来求schar%K
    while((unsigned)schar%K && n)
    {
        *schar++ = (unsigned char)c;
        n--;
    }

    lchar = (unsigned long*) schar;
    while ( n >= K ) {
        *lchar++ = fill;
        n -= K; //不知道这里如果用++和--会不会影响整体的效率
    }

    schar = (unsigned char*) lchar;
    while(n) //剩余的n
    {
        *schar++ = (unsigned char)c;
        --n;
    }
    return s;
}


5.20
double poly_optimized(double a[], double x, int degree)
{
    long int i;
    double result = 0;
    double s = 0, powx4 = 1;
    double x2 = x*x;
    double x4 = x2*x2;
    long int limit = degree-3;
    for(i = 0; i <= limit; i += 4)
    {
        double v1 = a[i] + a[i+1]*x;
        double v2 = a[i+2] + a[i+3]*x;
        v1 = v1 + v2 * x2;
        s = s + v1 * powx4;
        powx4 *= x4;
    }

    for(; i <= degree; ++i)
    {
        s += a[i]*powx4;
        powx4 *= x;
    }
    return s;
}
关键路径就是一个浮点数乘法,因此CPE是浮点乘法延迟的1/4,然而每次计算都需要load 4个值,所以CPE还是1.00。

5.21
void psum(float a[], float p[], long int n)
{
    long int i;
    int v = 0;
    for(i=0; i1
; i+=2)
    {
        int v1 = a[i];
        int v2 = a[i+1];
        v2 = v1 + v2;
        p[i] = v + v1;
        p[i+1] = v + v2;
        v = v + v2; 
    }
    
    for(; i     {
        v = v + a[i];
        p[i] = v;
    }
}

5.22
假设最开始需要100T的时间,那么A需要20T,B需要30T,C需要50T。
将B提到3倍,也就是B需要10T,那么总时间为80T。
将C提到1.5倍,也就是C需要33.3T,那么总时间为83.3T。
所以提高B会使得性能更优。




你可能感兴趣的:(深入理解计算机系统(第二版) 家庭作业 第五章)