循环展开不适用于其余元素

时间:2017-11-20 11:26:44

标签: c matrix-multiplication loop-unrolling

我有一个典型的矩阵乘法算法。我正在尝试应用并理解循环展开,但是当我尝试展开k次时,当k不是矩阵大小的倍数时,我遇到了实现算法的问题。 (结果我得到了非常大的数字)。这意味着我没有得到如何在展开后处理剩余的元素。这就是我所拥有的:

void Mult_Matx(unsigned long* a, unsigned long* b, unsigned long*c, long n)
{
    long i = 0, j = 0, k = 0;
    unsigned long sum, sum1, sum2, sum3, sum4, sum5, sum6, sum7;

    for (i = 0; i < n; i++)
    {
        long in = i * n;
        for (j = 0; j < n; j++)
        {
            sum = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = 0;

            for (k = 0; k < n; k += 8)
            {
                sum = sum + a[in + k] * b[k * n + j];
                sum1 = sum1 + a[in + (k + 1)] * b[(k + 1) * n + j];
                sum2 = sum2 + a[in + (k + 2)] * b[(k + 2) * n + j];
                sum3 = sum3 + a[in + (k + 3)] * b[(k + 3) * n + j];
                sum4 = sum4 + a[in + (k + 4)] * b[(k + 4) * n + j];
                sum5 = sum5 + a[in + (k + 5)] * b[(k + 5) * n + j];
                sum6 = sum6 + a[in + (k + 6)] * b[(k + 6) * n + j];
                sum7 = sum7 + a[in + (k + 7)] * b[(k + 7) * n + j];
            }

            if (n % 8 != 0)
            {
                for (k = 8 * (n / 8); k < n; k++)
                {
                    sum = sum + a[in + k] * b[k * n + j];
                }
            }
            c[in + j] = sum + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7;
        }
    }
}

让我们说大小又名n是12.当我展开它4次时,这段代码可以工作,这意味着它永远不会进入余数循环。但是,当它发生时,我正在忘记发生的事情!如果有人能指导我出错的地方,我真的很感激。我是新手,很难搞清楚。

1 个答案:

答案 0 :(得分:2)

在此形状上展开循环的一般方法:

for(int i=0; i<N; i++)
    ...

int i;
for(i=0; i<N-L; i+=L)
    ...
for(; i<N; i++)
    ...

或者如果你想将索引变量保留在循环的范围内:

for(int i=0; i<N-L; i+=L)
    ...
for(int i=L*(N/L); i<N; i++)
    ...

在这里,我使用整数除法向下舍入的事实。 L是您在第一个循环中执行的步骤数。

示例:

const int N=22;
const int L=6;
int i;
for(i=0; i<N-L; i+=L)
{
    printf("%d\n", i);
    printf("%d\n", i+1);
    printf("%d\n", i+2);
    printf("%d\n", i+3);
    printf("%d\n", i+4);
    printf("%d\n", i+5);
}
for(; i<N; i++)
    printf("%d\n", i);

但我建议你看看Duff's device。但是,我怀疑它并不总是一件好事。原因是模数是一项相当昂贵的操作。

不应该需要条件if (n % 8 != 0)。如果写得正确,for标题应该处理。