我的矩阵和内核之间的卷积序列代码如下所示:

int index1, index2, a, b;
for(int x=0;x<rows;++x){
    for(int y=0;y<columns;++y){
        for(int i=0;i<krows;++i){
            for(int j=0;j<kcolumns;++j){
                a=x+i-krows/2;
                b=y+j-kcolumns/2;
                if(a<0)
                    index1=rows+a;
                else if(a>rows-1)
                    index1=a-rows;
                else
                    index1=a;

                if(b<0)
                    index2=columns+b;
                else if(b>columns-1)
                    index2=b-columns;
                else
                    index2=b;

                output[x*columns+y]+=input[index1*columns+index2]*kernel[i*kcolumns+j];

            }
        }

    }
}

卷积考虑边界的循环处理。现在,我想将代码与openmp并行化。我考虑过将前两个for周期减少到一个,并使用以下语法:
#pragma omp parallel
#pragma omp for private(x,y,a, b, index1, index2)
for(int z=0;z<rows*columns;z++){
    x=z/columns;
    y=z%columns;
    ...

我看到这样的并行化可以减少cpu时间,但是我不是openmp的专家,所以我问自己是否还有其他更有效的解决方案。我认为同时并行化其他两个嵌套的for周期不是一个好主意。
使用尺寸为1000 * 10000的输入矩阵和9 * 9的方形核矩阵,我得到了以下时间:

1个线程4823 ms

2个线程2696 ms

4个线程2513毫秒。

我希望有人能给我一些有用的建议。那约化语法呢?

最佳答案

我的建议是完全改变方法。如果您对边界使用循环处理(即您的问题是周期性的),则快速的处理方法是基于基于fft的频谱方法:

-傅立叶变换矩阵和核
-计算产品
-逆傅立叶变换积(您具有卷积)

这(1)效率更高(除非内核的尺寸比矩阵的尺寸小得多),并且(2)您可以使用支持多线程(例如FFTW)的fft库并对其进行处理。

关于c++ - 剖析一些在openmp C++中嵌套的对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23835816/

10-14 07:12