C循环优化有助于最终分配

时间:2015-08-14 01:20:13

标签: c loops optimization

因此,对于我在计算机系统课程中的最终作业,我们需要优化这些forloops,使其比原始版本更快。使用我们的linux服务器,基本等级不到7秒,完整等级不到5秒。我在这里的代码大约需要5.6秒。我想我可能需要以某种方式使用指针来使它更快,但我不太确定。任何人都可以提供我的任何提示或选项吗?非常感谢你!

QUICKEDIT:文件必须保持50行或更少,我忽略了教师所包含的注释行。

#include <stdio.h>
#include <stdlib.h>

// You are only allowed to make changes to this code as specified by the comments in it.

// The code you submit must have these two values.
#define N_TIMES     600000
#define ARRAY_SIZE   10000

int main(void)
{
    double  *array = calloc(ARRAY_SIZE, sizeof(double));
    double  sum = 0;
    int     i;

    // You can add variables between this comment ...
    register double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0, sum7 = 0, sum8 = 0, sum9 = 0;
    register int j;
    // ... and this one.

    printf("CS201 - Asgmt 4 - \n");

    for (i = 0; i < N_TIMES; i++)
    {
        // You can change anything between this comment ...
        for (j = 0; j < ARRAY_SIZE; j += 10)
        {
            sum += array[j];
            sum1 += array[j + 1];
            sum2 += array[j + 2];
            sum3 += array[j + 3];
            sum4 += array[j + 4];
            sum5 += array[j + 5];
            sum6 += array[j + 6];
            sum7 += array[j + 7];
            sum8 += array[j + 8];
            sum9 += array[j + 9];
        }
        // ... and this one. But your inner loop must do the same
        // number of additions as this one does.
    }                   

    // You can add some final code between this comment ...
    sum += sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7 + sum8 + sum9;
    // ... and this one.

    return 0;
}

2 个答案:

答案 0 :(得分:3)

可能在正确的轨道上,虽然你需要对它进行测量以确定(我对测量的正常建议,而不是猜测在这里似乎有点多余因为作业的整个是要衡量的。)

优化编译器可能不会有太大差别,因为他们对这类东西非常聪明,但是,由于我们不知道它将在哪个优化级别进行编译,因此您可能会获得实质性的改进。

在内循环中使用指针是一个简单的事情,首先添加一个指针变量:

register double *pj;

然后将循环更改为:

for (pj = &(array[0]); pj < &(array[ARRAY_SIZE]); j++) {
        sum += *j++;
        sum1 += *j++;
        sum2 += *j++;
        sum3 += *j++;
        sum4 += *j++;
        sum5 += *j++;
        sum6 += *j++;
        sum7 += *j++;
        sum8 += *j++;
        sum9 += *j;
    }

这使得循环中的添加量保持不变(假设您将+=++计为加法运算符,当然)但基本上使用指针而不是数组索引。

在我的系统上没有优化 1 ,这将它从9.868秒(CPU时间)降至4.84秒。您的里程可能会有所不同。

1 使用优化级别-O3两者报告为耗时0.001秒,因此,如上所述,优化程序非常漂亮聪明。但是,如果你看到5秒以上,我建议它没有经过优化编译。

顺便说一下,这是一个很好的理由,为什么通常建议以可读的方式编写代码,让编译器负责让它运行得更快。虽然我对优化的微薄尝试大致使速度加倍,但使用-O3使其运行速度快了: - )

答案 1 :(得分:0)

在其他任何事情之前,尝试更改编译器设置以生成更快的代码。有一般优化,编译器可能会进行自动矢量化。

你总是会尝试几种方法并检查最快的方法。作为目标,尝试每次添加或更好地达到一个周期。

每个循环的迭代次数:您同时累加10个和。可能是您的处理器没有足够的寄存器,或者它有更多。我测量每个循环4,5,6,7,8,9,10,11,12,13,14 ......的时间。

总和数量:拥有多个总和意味着延迟不会让您受到影响,只是吞吐量。但超过四六个可能没有帮助。尝试四个总和,每个循环进行4次,8次,12次,16次迭代。或六次总和,6次,12次,18次迭代。

缓存:您正在运行80,000字节的数组。可能超过L1缓存。将阵列分成2或4个部分。做一个外循环迭代两个或四个子数组,下一个循环从0到N_TIMES - 1,内循环加起来值。

然后您可以尝试使用矢量操作,或者多线程化代码,或者使用GPU来完成工作。

如果你被迫不使用优化,那么&#34;注册&#34;关键字实际上可行。