Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.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
如何解决OpenACC中PGI编译器中使用-fast时阻止循环矢量化的循环携带依赖_C_For Loop_Openacc_Pgi - Fatal编程技术网

如何解决OpenACC中PGI编译器中使用-fast时阻止循环矢量化的循环携带依赖

如何解决OpenACC中PGI编译器中使用-fast时阻止循环矢量化的循环携带依赖,c,for-loop,openacc,pgi,C,For Loop,Openacc,Pgi,我想用C语言中的OpenACC并行化一个基于粒子方法的流体流代码。我是OpenACC的新手,目前正在将其应用到多核计算机上的代码中,并试图理解其基础知识。稍后,我将尝试将其卸载到GPU。我在代码中的for循环中添加了一些#pragma。在部分代码中,当我编译没有-fast的代码时,它编译没有任何问题,但只并行化外部循环,然而,当我在编译代码时包含-fast时,它会给我一些数据依赖性消息,而内部循环不会并行化。在阅读了现有的文献之后,我尝试了很多事情,包括使用带有指针声明的restrict,以及使

我想用C语言中的OpenACC并行化一个基于粒子方法的流体流代码。我是OpenACC的新手,目前正在将其应用到多核计算机上的代码中,并试图理解其基础知识。稍后,我将尝试将其卸载到GPU。我在代码中的for循环中添加了一些#pragma。在部分代码中,当我编译没有-fast的代码时,它编译没有任何问题,但只并行化外部循环,然而,当我在编译代码时包含-fast时,它会给我一些数据依赖性消息,而内部循环不会并行化。在阅读了现有的文献之后,我尝试了很多事情,包括使用带有指针声明的restrict,以及使用原子和例程语句等,但到目前为止似乎没有任何效果。守则部分的摘要如下:

// the code intends to compute the total number of neighbour particles of "iParticle" in 
// particle.numberOfNeighborParticles[iParticle] and saves the list of these neighbour particles in
// particle.neighborTable[iParticle][Neigh]

int iX, iY;
#pragma acc parallel loop private(iX, iY)                                       //line 98
for (iParticle = 0; iParticle < particle.totalNumber; iParticle++)
{
    BUCKET_findBucketWhereParticleIsStored(&iX, &iY, iParticle, position);

#pragma acc loop seq                                                           // line 133
    for (jX = iX - 1; jX <= iX + 1; jX++)
    {
       .....
#pragma acc loop seq                                                           // line 179
        for (jY = iY - 1; jY <= iY + 1; jY++)
        {
     ......
#pragma acc loop                                                              // line 186
            for (iStoredParticle = 0; iStoredParticle < domain.bucket[jX][jY].count; iStoredParticle++)
            {
                jParticle = domain.bucket[jX][jY].list[iStoredParticle];

                xij = (position[XDIM][jParticle] - position[XDIM][iParticle]);

                distanceIJ_squared = xij * xij;

                yij = (position[YDIM][jParticle] - position[YDIM][iParticle]);
                distanceIJ_squared += yij * yij;
                if (distanceIJ_squared > parameter.maxRadius_squared)
                    continue;

                NEIGH_addParticleInNeighborTable(iParticle, jParticle, particle.numberOfNeighborParticles, particle.neighborTable);
            }
        }
    }
}

//The *NEIGH_addParticleInNeighborTable()* function is as under:

void
NEIGH_addParticleInNeighborTable( 
                                 int iParticle
                                 ,int jParticle
                                 ,int *restrict numberOfNeighborParticles
                                 ,int **restrict neighborTable
                                 ){

  int iNeigh;
    iNeigh = numberOfNeighborParticles[iParticle];
    neighborTable[iParticle][iNeigh] = jParticle;
    #pragma acc atomic
    numberOfNeighborParticles[iParticle]++; 
}

//该代码打算计算中“iParticle”的相邻粒子总数
//particle.numberOfNeighborParticles[iParticle]并将这些相邻粒子的列表保存在中
//particle.neightable[iParticle][Neigh]
int iX,iY;
#pragma acc并行环路专用(iX,iY)//第98行
对于(iParticle=0;iParticle对于(jX=iX-1;jX请注意,这不是OpenACC的问题,编译器只是告诉您它无法对循环进行矢量化(矢量化是通过-fast或-O2启用的)由于潜在的循环依赖于particle.numberOfNeighborParticles和particle.neighborTable。这不会影响您的结果,也不会影响循环的OpenACC并行化,您将无法获得矢量化带来的额外性能好处


您可以尝试添加标志“-Msafeptr”您向编译器声明没有指针别名,这通常会导致这些类型的问题。警告是,如果您有别名,代码可能会得到不正确的结果。

对于第二个已编辑的问题,只要更新计数的顺序无关紧要,就可以使用原子捕获instead。这将把count的值捕获到一个局部变量中,这样您就不必担心它的变化。例如:

int cnt;
#pragma acc atomic capture 
{
    cnt = count; 
    count++;
}
contiguous_state[iState][cnt]=jState;  

如果计数顺序确实重要,则循环不可并行。

感谢您的宝贵见解和建议。NEIGH_addParticleInNeighborTable()函数中似乎存在竞争条件,这会在内部循环的矢量化中产生问题。NumberOfNeigorParticles[iParticle]的初始值对于所有导致争用条件的“向量线程”都将为零。OpenACC中是否有任何函数可用于获取内环的“向量线程”的数字ID,该ID可用于初始化iNeigh变量?OpenACC标准没有“线程ID”,主要是因为枚举取决于目标设备。We(PGI)提供扩展名“uu pgi_vectoridx”来获取向量id,但是如果我们忽略“vector”而只在目标多核时使用“gang”,那么它在这里就没有多大用处了。此外,它返回一个gang中的向量id,而不是枚举的全局向量id。要获取该扩展名,需要使用“id=(u pgi_gangidx()*num_gangs)+u pgi_vectoridx()”“num_gangs”将是一个用户变量,也用于通过“num_gangs”来固定帮派数量“子句。我不想在这里使用它。虽然我不知道您是代码,但从您描述的情况来看,这种竞争条件是否会阻止外循环的并行化?@Mat Colgrove很抱歉,我之前添加的代码非常复杂。现在我编辑了这个问题,并添加了一个伪代码(有点)详细阐述这个问题。希望它能澄清外环没有种族条件,并解释手头的问题。请您提出解决这个问题的建议/意见。谢谢
int cnt;
#pragma acc atomic capture 
{
    cnt = count; 
    count++;
}
contiguous_state[iState][cnt]=jState;