C++ 为什么并行版本比较慢?

C++ 为什么并行版本比较慢?,c++,parallel-processing,openmp,C++,Parallel Processing,Openmp,我想在矩阵上应用特定的过滤器。(从[0][0]顺序到结尾) A[i][j]=0.2*(A[i][j]+A[i+1][j]+A[i-1][j]+A[i][j+1]+A[i][j-1]) 如果[i],[j]是例如[0][0](矩阵中的第一个值),则我使用零作为左侧和上方的值 我试图理解为什么我的代码的并行版本比顺序版本慢 当我使用多个线程进行计算时,我使用的是对角线上有独立的功这一事实。我故意将矩阵扩展为两行两列(用零填充),以简化滤波器的计算 我还尝试了矩阵的各种维度(高达7000x7000) 我

我想在矩阵上应用特定的过滤器。(从[0][0]顺序到结尾)

A[i][j]=0.2*(A[i][j]+A[i+1][j]+A[i-1][j]+A[i][j+1]+A[i][j-1])

如果[i],[j]是例如[0][0](矩阵中的第一个值),则我使用零作为左侧和上方的值

我试图理解为什么我的代码的并行版本比顺序版本慢

当我使用多个线程进行计算时,我使用的是对角线上有独立的功这一事实。我故意将矩阵扩展为两行两列(用零填充),以简化滤波器的计算

我还尝试了矩阵的各种维度(高达7000x7000)

我的问题是:

顺序版本:

for(int i=1;i
并行版本:

int n=r-2;
对于(int slice=0;slice<2*n-1;++slice){//沿对角线
intz=(切片对于(int j=z;j如果您计算出循环的顺序版本中发生了什么,您将看到内部循环访问顺序内存地址(或者更准确地说,三个内存范围,每个范围的地址按顺序访问)

现代的CPU非常好,可以处理连续的内存地址。这就是为什么在许多使用情况下,
std::vector
在直觉上比
std::list
更快的原因

现在,对循环的并行版本也做同样的操作。用铅笔在纸上计算出每个线程最终到达的位置。看起来它在矩阵中垂直迭代,跨越多个单独分配的行。这不是连续的内存地址,而是到处都是;这是不太理想的

您只需让每个线程捕获它正在破坏的原始内存地址,并查看所有执行线程的组合捕获日志,就可以轻松地完成这项工作;现在将其与顺序版本的相同日志进行比较


雪上加霜的是:在典型的现代架构中,内存区域被划分为更大的块,称为“缓存线”。看起来并行版本将有多个执行线程访问相邻的内存地址,其中许多线程将落入同一缓存线;当多个CPU执行单元必须写入同一缓存线时,即使写入每个缓存线内的不同地址,它们也必须执行复杂的歌舞路由ine,以避免互相踩到对方的脚。

您正在以一种非常简单的方式创建2d数组。行数据散布在堆中。如果您将整个2d数组数据分配到连续内存中,则差异可能会减小。