c++ - : How to make threads write to private arrays and merge all the arrays once all the threads finished processing 并行 omp

标签 c++ multithreading parallel-processing openmp

我需要计算 z 值,将它们放入数组 Bs2

我尝试使用 omp parallel for 并行化处理。

我看到的一个问题是,如果我不将 B[i][j] += zs2[i] += z 语句放在 critical 部分,我看到生成了很多 NaN 值。

只是想知道是否有办法将 z 值写入单独的数组(每个线程一个数组)并在最后合并它们。

非常感谢任何帮助。

#pragma omp parallel
{
    double z;
    #pragma omp parallel for
    for(int t=1; t<n; t++) {
        double phi_i[N];
        double obs_j_seq_t[N];

        for(int i=0; i<N; i++) {
            for(int j=0; j<N; j++) {
                z=phi_i[i]*trans[i*N + j]*obs_j_seq_t[j]*beta[t*N+j]/c[t]; 
                #pragma omp critical
                { 
                    B[i][j] += z;
                    s2[i] += z;
                }
            }
        }
    }
}

最佳答案

您的代码暴露了一些问题,每个问题都是其性能和/或有效性的潜在 killer :

  • 首先使用#pragma omp parallel,然后添加#pragma omp parallel for。这意味着您正在尝试生成嵌套并行性(另一个并行区域内的并行区域)。首先,这是一个坏主意,其次,默认情况下禁用。因此,您的第二个 parallel 指令将被忽略,您的循环中的工作永远不会被分发,并由您使用初始 parallel 指令生成的所有线程完全执行。因此,所有线程同时将结果写入 Bs2 时存在竞争条件。您通过添加 critical 部分解决了问题,但从根本上说,代码是错误的。
  • 即使您没有这个初始的 parallel 指令或启用嵌套并行性,您的代码也会因为以下原因而出错:
    • 您的 z 变量在第二个 parallel 区域的线程之间共享,因为它被所有线程修改,所以它的值为一旦在该区域中产生了一个以上的线程,就未定义。
    • 更根本的是,您尝试在 t 上并行化循环,但解决方案是在 i 上索引的。这意味着所有线程将竞争更新相同的索引,再次导致竞争条件和无效结果。您可以再次使用 critical 指令来解决这个问题,但这只会使代码变得非常慢。您最好将 i 上的循环并行化(同时可能交换 ti 上的循环,将后者放在最外层)。

您的代码可能会变成这样(未测试):

#pragma omp parallel for
for(int i=0; i<N; i++) {
    for(int t=1; t<n; t++) {
        double phi_i[N];       // I guess these need some initialization
        double obs_j_seq_t[N]; // Idem
        for(int j=0; j<N; j++) {
            double z=phi_i[i]*trans[i*N + j]*obs_j_seq_t[j]*beta[t*N+j]/c[t]; 
            B[i][j] += z;
            s2[i] += z;
        }
    }
}

关于c++ - : How to make threads write to private arrays and merge all the arrays once all the threads finished processing 并行 omp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40289248/

相关文章:

c++ - 从 std::apply 中的折叠表达式捕获返回值

c++ - 将 PVS-Studio 集成到 MSBuild 文件中

c++ - 生产者/消费者模式的 STL 容器线程安全

python - 为什么joblib.Parallel()比非并行计算花费更多的时间? Parallel()的运行速度是否应该比非并行计算快?

c++ - 使用 vfork 的多线程

c++ - Qt中的logicalDpiX和physicalDpiX有什么区别?

c++ - 为派生类的 vector 调用适当的方法

java - 使用线程和 Swing 显示更新延迟

无法编译调用 tgkill 的程序

Ruby VM 并发性和并行性