Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Arrays 如何使用openmp并行化阵列元素的移动_Arrays_Algorithm_Parallel Processing_Openmp - Fatal编程技术网

Arrays 如何使用openmp并行化阵列元素的移动

Arrays 如何使用openmp并行化阵列元素的移动,arrays,algorithm,parallel-processing,openmp,Arrays,Algorithm,Parallel Processing,Openmp,如果阵列非常大,下面的代码段在我的程序中是最耗时的。最后一个是这个数组结束位置的变量,Idx是数组特定位置的变量,所以我想要的是将部分数组元素从Idx向后移动1 for(long i = last; i >= Idx; i--) { pArray[i] = pArray[i-1]; } 我只是尝试使用parallel for来并行化它,但它肯定不能工作。谁能告诉我这段代码是否可以与openmp并行?如果是,如何编码?谢谢 #pragma omp parallel for for(

如果阵列非常大,下面的代码段在我的程序中是最耗时的。最后一个是这个数组结束位置的变量,Idx是数组特定位置的变量,所以我想要的是将部分数组元素从Idx向后移动1

for(long i = last; i >= Idx; i--)
{
    pArray[i] = pArray[i-1];
}
我只是尝试使用parallel for来并行化它,但它肯定不能工作。谁能告诉我这段代码是否可以与openmp并行?如果是,如何编码?谢谢

#pragma omp parallel for
for(long i = last; i >= Idx; i--)
{
    pArray[i] = pArray[i-1];
}

可以将阵列划分为多个块。 因此,每个线程将只在其块上工作

例如,如果数组的大小为1000,并且有4个线程,那么第一个线程将移动块1-198中的值,第二个线程将移动块201-398中的值,依此类推。 不要忘记在边界上移动值的特殊情况(例如200到199)


您不需要为创建“并行”,只有“并行”区域才有用。

您可以将阵列划分为多个块。 因此,每个线程将只在其块上工作

例如,如果数组的大小为1000,并且有4个线程,那么第一个线程将移动块1-198中的值,第二个线程将移动块201-398中的值,依此类推。 不要忘记在边界上移动值的特殊情况(例如200到199)


您不需要为“并行”创建“并行”,只有“并行”区域才有用。

您的主要问题是代码具有循环携带的依赖关系,即迭代之间存在依赖关系

因此,您的代码是:

for(long i = last; i >= Idx; i--)
{
  pArray[i] = pArray[i-1];
}
现在,让我们假设
last=4
Idx=1
。你会有这样的想法:

  iteration 0: pArray[4] = pArray[3];
  iteration 1: pArray[3] = pArray[2];
  iteration 2: pArray[2] = pArray[1];
  iteration 3: pArray[1] = pArray[0];
如果将其与四个线程并行(假设是静态的),并且线程0被分配为迭代0,线程1被分配为迭代1,等等,那么根据首先执行的线程的不同,您将得到不正确的结果。如果线程0在线程1之前执行,线程0将使用
pArray[3]
的旧值,而如果线程0在线程1之后执行,线程0将使用由线程1计算的
pArray[3]
的新值

因为迭代不是独立的,所以循环不能直接并行化


显然,您只想将数组的值向前移动一个位置,因此我认为更好的方法是使用指针算法或重新组织循环和其他代码片段,以尝试消除依赖项或完全消除循环。

您的主要问题是代码具有循环携带的依赖项,即迭代之间存在依赖关系

因此,您的代码是:

for(long i = last; i >= Idx; i--)
{
  pArray[i] = pArray[i-1];
}
现在,让我们假设
last=4
Idx=1
。你会有这样的想法:

  iteration 0: pArray[4] = pArray[3];
  iteration 1: pArray[3] = pArray[2];
  iteration 2: pArray[2] = pArray[1];
  iteration 3: pArray[1] = pArray[0];
如果将其与四个线程并行(假设是静态的),并且线程0被分配为迭代0,线程1被分配为迭代1,等等,那么根据首先执行的线程的不同,您将得到不正确的结果。如果线程0在线程1之前执行,线程0将使用
pArray[3]
的旧值,而如果线程0在线程1之后执行,线程0将使用由线程1计算的
pArray[3]
的新值

因为迭代不是独立的,所以循环不能直接并行化


显然,您只想将数组的值向前移动一个位置,因此我认为更好的方法是使用指针算法或重新组织循环和其他代码片段,以尝试完全消除依赖关系或循环。

您想要的是并行执行
memmove
。这里有一个例子,可以满足您的需要

#include <stdio.h>
#include <string.h>
#include <omp.h>

#define N 20

int main() {  
    int x[N+1];
    for(int i=0; i<N; i++) x[i] = i+1;
    for(int i=0; i<N; i++) printf("%d ", x[i]); puts("");
    #pragma omp parallel
    {
        int ithread = omp_get_thread_num(), nthreads = omp_get_num_threads();
        size_t pos = ithread*N/nthreads;
        size_t n = (ithread+1)*N/nthreads - pos - 1;
        int tmp = x[pos+n];
        memmove(&x[pos+1], &x[pos], sizeof *x*n);
        #pragma omp barrier
        x[pos+n+1] = tmp;   
    }
    for(int i=0; i<N+1; i++) printf("%d ", x[i]); puts("");
}
#包括
#包括
#包括
#定义n20
int main(){
整数x[N+1];

对于(int i=0;i您想要的是并行执行
memmove
。下面是一个执行您想要的操作的示例

#include <stdio.h>
#include <string.h>
#include <omp.h>

#define N 20

int main() {  
    int x[N+1];
    for(int i=0; i<N; i++) x[i] = i+1;
    for(int i=0; i<N; i++) printf("%d ", x[i]); puts("");
    #pragma omp parallel
    {
        int ithread = omp_get_thread_num(), nthreads = omp_get_num_threads();
        size_t pos = ithread*N/nthreads;
        size_t n = (ithread+1)*N/nthreads - pos - 1;
        int tmp = x[pos+n];
        memmove(&x[pos+1], &x[pos], sizeof *x*n);
        #pragma omp barrier
        x[pos+n+1] = tmp;   
    }
    for(int i=0; i<N+1; i++) printf("%d ", x[i]); puts("");
}
#包括
#包括
#包括
#定义n20
int main(){
整数x[N+1];

对于(int i=0;i什么是pArray?也许你可以使用
memcpy
(它可以比任何并行化都快)你想做的事情都有内存依赖性。它不会像openmp那样工作,但选项1:你可以尝试临时数组或选项2:划分工作负载(数组)手动操作,使不超过1个线程可以访问内存位置。如果您只有1个内存控制器,memcpy应该提供良好的性能。如果您拆分为块,则必须处理源与目标重叠。memcpy无法处理内存重叠,memmove可以通过使用临时数组来实现这一点,这意味着工作人员需要被复制两次,我将尝试检查性能。memcopy可以通过自动反转循环来处理重叠。你是对的,memcpy可能会跳过这一步。pArray是什么?也许你可以使用
memcpy
(它可能比任何并行都快)您要执行的操作与内存有关。它不会像openmp那样工作,但选项1:您可以尝试临时阵列或选项2:分配工作负载(阵列)手动操作,使不超过1个线程可以访问内存位置。如果您只有1个内存控制器,memcpy应该提供良好的性能。如果您拆分为块,则必须处理源与目标重叠。memcpy无法处理内存重叠,memmove可以通过使用临时数组来实现这一点,这意味着工作人员需要如果被复制两次,我将尝试检查性能。memcopy可以通过自动反转循环来处理重叠。memcpy可能会跳过该步骤,这是对的。在这种情况下,您需要对
进行并行处理(如果不存在依赖项)。如果您只使用一个
并行
,则该区域中的每个线程将执行循环的所有迭代,而不是在线程之间分配迭代。我基本上实现了您用文字所说的内容(尽管我在详细阅读您的答案之前已经实现了)。您需要