Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以为并行区域中的共享二维阵列创建select元素的线程本地副本吗?(共享、专用、屏障:OPenMP)_C++_Multithreading_Openmp_Barrier - Fatal编程技术网

C++ 可以为并行区域中的共享二维阵列创建select元素的线程本地副本吗?(共享、专用、屏障:OPenMP)

C++ 可以为并行区域中的共享二维阵列创建select元素的线程本地副本吗?(共享、专用、屏障:OPenMP),c++,multithreading,openmp,barrier,C++,Multithreading,Openmp,Barrier,我有一个由nxn元素组成的二维网格。在一次迭代中,我通过平均相邻元素的值来计算一个元素的值。即: for(int i=0;i<n;i++) for(int j=0;j<n;j++) grid[i][j] = (grid[i-1][j] + grid[i][j-1] + grid[i+1][j] + grid[i][j+1])/4.0; for(int i=0;i 实际上,您希望拥有的线程比网格点少(多得多),因此每个线程将计算一大堆点

我有一个由
n
x
n
元素组成的二维网格。在一次迭代中,我通过平均相邻元素的值来计算一个元素的值。即:

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            grid[i][j] = (grid[i-1][j] + grid[i][j-1] + grid[i+1][j] + grid[i][j+1])/4.0;
for(int i=0;i
  • 实际上,您希望拥有的线程比网格点少(多得多),因此每个线程将计算一大堆点(例如,一行)线程,您的程序将受到内存限制,而不是CPU限制。因此,在每个网格点上启动一个线程将无法实现并行计算的全部目的。因此,不建议使用您的想法#1(尽管我不太确定我是否正确理解了它;也许这不是您的建议)

  • 我建议(其他人在OP评论中也指出)分配两倍存储网格值所需的内存,并使用两个在迭代之间交换的指针:一个指向保存以前的只读迭代值的内存,另一个指向只写的新迭代值。请注意,您将只交换指针,而不是实际复制内存。在迭代之后完成后,您可以将最终结果复制到所需位置

  • 是的,您需要在迭代之间同步线程,但是在OpenMP中,这通常是通过在迭代循环中打开一个并行区域隐式完成的(在并行区域的末尾有一个隐式屏障):

    第二个版本将自动在可用线程之间平均分配工作,这很可能是您想要的。在第一个版本中,您必须手动执行

  • 实际上,您希望拥有的线程比网格点少(多得多),因此每个线程将计算一大堆点(例如,一行)线程,您的程序将受到内存限制,而不是CPU限制。因此,在每个网格点上启动一个线程将无法实现并行计算的全部目的。因此,不建议使用您的想法#1(尽管我不太确定我是否正确理解了它;也许这不是您的建议)

  • 我建议(其他人在OP评论中也指出)分配两倍存储网格值所需的内存,并使用两个在迭代之间交换的指针:一个指向保存以前的只读迭代值的内存,另一个指向只写的新迭代值。请注意,您将只交换指针,而不是实际复制内存。在迭代之后完成后,您可以将最终结果复制到所需位置

  • 是的,您需要在迭代之间同步线程,但是在OpenMP中,这通常是通过在迭代循环中打开一个并行区域隐式完成的(在并行区域的末尾有一个隐式屏障):

    第二个版本将自动在可用线程之间平均分配工作,这很可能是您想要的。在第一个版本中,您必须手动执行


  • 当前,您正在基于同一数组的邻居计算平均值,并立即将其写入当前数组元素。顺便说一句,由于依赖性,这看起来很可疑。一旦转到并行线程,您将不得不执行非常复杂的同步方案,让正确的线程等待其他线程的结果。即,网格[2][2]的计算更新必须等到[1][1]、[3,2]的计算完成所有其他邻域都完成了。其他邻域应该等待gheir邻域,…否则您将有未定义的行为。这是您想要的吗?您应该能够找到关于jacobi迭代并行性的有用讨论。它可能超出临界状态。一个简单的方法是将所有工作保存到第二个网格。当您的计算完成时全部完成您可以交换grid和grid2。如何效率低下?内存?您需要2个拷贝,这是您无论如何都需要的。它可以是OpenMP友好的,并且当以正确的方式处理(交换指针)时,后循环更新可以非常快@complextea在您的示例中,它不是这样工作的。您使用以前在其他迭代中计算的平均值。您需要第二个数组来保存结果。在这种情况下,您可以在每次迭代中使用线程,而无需任何同步(除了“join”之外)。很可能这是一个过度杀戮。您只需要定义其中的几个,即8和重用。当前,您正在基于同一数组的邻居计算平均值,并立即将其写入当前数组元素。顺便说一句,由于依赖性,这看起来可疑。一旦转到并行线程,您将不得不执行非常复杂的操作复杂的同步方案,允许正确的线程等待其他线程的结果。例如,网格[2][2]的计算更新必须等待[1][1]、[3,2]的计算所有其他邻域都完成了。其他邻域应该等待gheir邻域,…否则您将有未定义的行为。这是您想要的吗?您应该能够找到关于jacobi迭代并行性的有用讨论。它可能超出临界状态。一个简单的方法是将所有工作保存到第二个网格。当您的计算完成时全部完成您可以交换grid和grid2。如何效率低下?内存?您需要2个拷贝,这是您无论如何都需要的。它可以是OpenMP友好的,并且当以正确的方式处理(交换指针)时,后循环更新可以非常快.@complextea在您的示例中,它不是这样工作的。您使用以前在其他迭代中计算的平均值。您需要第二个数组来保存结果。在这种情况下,您可以在每次迭代中使用线程,而无需任何同步(除了“join”)。这很可能是一种过度使用
    for (int iter = 0; iter < niter; ++iter)
    {
        #pragma omp parallel
        {
            // get range of points for current thread
            // loop over thread's points and apply the stencil
        }
    }
    
    const int np = n*n;
    for (int iter = 0; iter < niter; ++iter)
    {
        #pragma omp parallel for
        for (int ip = 0; ip < np; ++ip)
        {
            const int i = ip / n;
            const int j = ip % n;
            // apply the stencil to [i,j]
        }
    }