如何使C编译器将所有嵌套循环转换为单个循环

Mar*_*tin 1 c gcc clang icc compiler-optimization

假设有四个嵌套循环,具有不同的循环计数器和条件.有没有办法告诉编译器(icc,gcc和clang)将所有循环转换为一个循环?

N=128; M=128; P=3; Q=3; //All these variables are constant
for (n=0; n<N; n++){
    for(m=0; m<M; m++){
        temp=0;
        for(p=0; p<P; p++){ 
            for(q=0; q<Q; q++){
                temp += kernel[p][q] * input[n+p][m+q];
            }
        }
        output[n][m]=temp;
    }
}
Run Code Online (Sandbox Code Playgroud)

要转变为:

for(;;)
    //computations...
Run Code Online (Sandbox Code Playgroud)

根据我的经验,当您依赖自动矢量化时,这非常有用.如果有办法转换两个嵌套循环也可以.有些东西解决了这个问题,但手写代码.我有一个程序,你可以看到它在这里的godbolt.

ike*_*ami 5

我不知道你为什么要这样,但你可以手动完成.

int accumulator;
for (int i=0; i<N*M*P*Q; ++i) {
    int n = i;
    int q = n % Q;  n /= Q;
    int p = n % P;  n /= P;
    int m = n % M;  n /= M;

    if (!p && !q)
       accumulator = 0;

    accumulator += kernel[p][q] * input[n+p][m+q];

    if (!p && !q)
        output[n][m] = accumulator;
}
Run Code Online (Sandbox Code Playgroud)

两个循环更有意义.

for (int i=0; i<N*M; ++i) {
    int n = i / M;
    int m = i % M;

    int accumulator = 0;
    for (int j=0; j<P*Q; ++j) {
        int p = j / Q;
        int q = j % Q;
        accumulator += kernel[p][q] * input[n+p][m+q];
    }    

    output[n][m] = accumulator;
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议OP检查编译器的自动矢量化输出以及它的原始代码并进行比较. (3认同)