c++ - 使用 OpenMP 的较慢代码如何并行化?

标签 c++ performance parallel-processing openmp icc

此代码使用 OpenMP 时速度较慢。没有 OpenMP,我得到大约 10 秒。使用 OpenMP 我得到大约 40 秒。怎么了?非常感谢各位 friend !

for (i=2;i<(nnoib-2);++i){
    #pragma omp parallel for
    for (j=2; j<(nnojb-2); ++j) {
        C[i][j]= absi[i]*absj[j]*
                 (2.0f*B[i][j] + absi[i]*absj[j]*
                 (VEL[i][j]*VEL[i][j]*fat*
                 (16.0f*(B[i][j-1]+B[i][j+1]+B[i-1][j]+B[i+1][j])
                 -1.0f*(B[i][j-2]+B[i][j+2]+B[i-2][j]+B[i+2][j]) 
                 -60.0f*B[i][j]
                 )-A[i][j]));
        c2 = (abs(C[i][j]) > Amax[i][j]);
        if (c2) {
            Amax[i][j] = abs(C[i][j]);
            Ttra[i][j] = t;
        }
    }
}

最佳答案

仅仅因为您正在使用 OpenMP 并不意味着您的程序会运行得更快。这里可能会发生几件事:

  1. 产生每个线程都会产生成本,如果您产生一个线程来执行少量计算,那么产生线程本身将花费比计算更多的时间。

    <
  2. 默认情况下,OpenMP 将生成您的 CPU 支持的最大线程数。对于每个内核支持 2 个或更多线程的 CPU,线程将竞争每个内核的资源。使用 omp_get_num_threads(),您可以看到默认情况下会产生多少线程。我建议尝试使用 omp_set_num_threads() 以该值的一半运行代码。

您是否确认使用和不使用 OpenMP 的结果相同?变量 j 和 c2 似乎存在依赖关系。您应该将它们声明为每个线程私有(private):

#pragma omp parallel for private(j,c2)

我想补充一点:在尝试任何并行化之前,您应该确保代码已经过优化。

根据您的编译器、编译器标志和指令的复杂性,编译器可能会也可能不会优化您的代码:

// avoid calculation nnoib-2 every iteration
int t_nnoib = nnoib - 2;
for (i=2; i< t_nnoib; ++i){
    // avoid calculation nnojb-2 every iteration
    int t_nnojb = nnojb - 2;
    // avoid loading absi[i] every iteration
    int t_absi = absi[i];
    for (j=2; j< t_nnojb; ++j) {
        C[i][j]= t_absi * absj[j] *
             (2.0f*B[i][j] + t_absi * absj[j] *
             (VEL[i][j] * VEL[i][j] * fat *
             (16.0f * (B[i][j-1] + B[i][j+1] + B[i-1][j] + B[i+1][j])
              -1.0f * (B[i][j-2] + B[i][j+2] + B[i-2][j] + B[i+2][j]) 
              -60.0f * B[i][j]
             ) - A[i][j]));

        // c2 is a useless variable
        if (abs(C[i][j]) > Amax[i][j]) {
            Amax[i][j] = abs(C[i][j]);
            Ttra[i][j] = t;
         }
    }
}

它可能看起来不多,但它会对您的代码产生巨大的影响。编译器将尝试将局部变量放在寄存器中(访问时间要快得多)。请记住,您不能无限期地应用此技术,因为您的寄存器数量有限,滥用它会导致您的代码遭受寄存器溢出的困扰。

在数组 absi 的情况下,您将避免让系统在执行 j 循环期间在缓存中保留该数组的一部分。这种技术的总体思路是将任何不依赖于内循环变量的数组访问移至外循环。

关于c++ - 使用 OpenMP 的较慢代码如何并行化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15318331/

相关文章:

c++ - 如何在 OpenCV 中使用相机

mysql - 具有大量条目的可轻松过滤的数据库表

c# - 我可以阻止用户修改C#中的参数吗

c - 关键部分中的函数在 OpenMP 中产生数据竞争

c# - Unity,c++ native 插件不匹配的字节数组

c++ - 如何填充项目为 8 个字符的集合? (std::set<字符[8]>)

iphone - 如何在运行时更改iPhone应用程序语言?

comm_split 奇怪的行为?

c - CUDA 中的每线程哈希表类数据结构实现

c++ - 通过最多进行 2 笔交易找到您可以赚到的最大钱(找到列表中两个最大的非重叠增加)