我的矩阵和内核之间的卷积序列代码如下所示:
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/