我的矩阵和内核之间的卷积串行代码的工作原理如下:
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的专家,所以我问自己是否还有其他更有效的解决方案。我认为并行化其他 2 个嵌套 for 循环并不是一个好主意。 使用尺寸为 1000*10000 的输入矩阵和 9*9 方核矩阵,我得到这些时间:
1 个线程为 4823 毫秒
2 个线程为 2696 毫秒
4 个线程需要 2513 毫秒。
希望有人能给我一些有用的建议。 for 缩减语法怎么样?
最佳答案
我的建议是完全改变方法。如果您对边界使用循环处理(即您的问题是周期性的),那么快速的方法是基于基于 fft 的频谱方法:
-傅里叶变换矩阵和核 - 计算产品 -对乘积进行逆傅立叶变换(您有卷积)
这(1)效率更高(除非内核的尺寸比矩阵的尺寸小得多)并且(2)您可以使用支持多线程的 fft 库(如 FFTW)并让它处理它。
关于c++ - 对 openmp C++ 中的一些嵌套进行并行化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23835816/