c++ - 对 openmp C++ 中的一些嵌套进行并行化

标签 c++ multithreading c++11 parallel-processing openmp

我的矩阵和内核之间的卷积串行代码的工作原理如下:

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/

相关文章:

C++ - 如何写入和读取包含对象的结构? (写入和读取二进制文件)

c++ - 如果我只想指定一个哈希函数,我应该将什么传递给 unordered_map 的存储桶计数参数?

java - Spring Batch 分区 + 线程

java - `ArrayList::get` 是线程安全的吗?

java - 从另一个线程初始化同一类的静态字段时访问静态方法

c++ - 访问 POD 结构数组作为其单个成员的数组是否违反严格别名?

C++:通用函数包装类作为非模板类​​的成员

c++ - 使用 'ofstream' 代码错误写入文本文件

c++ - 如何将指针保存到重新定义的运算符?

c++ - 为什么它给出派生版本?