Arrays 使用递归指针与OpenACC进行并行FOR循环

Arrays 使用递归指针与OpenACC进行并行FOR循环,arrays,c,pointers,parallel-processing,openacc,Arrays,C,Pointers,Parallel Processing,Openacc,我有一个与OpenMP并行的FOR循环: #pragma omp parallel用于默认(无)私有(k,cell)共享(sim,mesh) 对于(i=0;incells;i++){ 单元=&(网格->单元[i]); 对于(k=0;knvar;k++){ 单元格->U_辅助[k]=单元格->U[k]; cell->U[k]=sim->dt*((cell->w2->fL_星[k]-cell->w4->fR_星[k])/cell->dx+(cell->w3->fL_星[k]-cell->w1->fR

我有一个与OpenMP并行的FOR循环:

#pragma omp parallel用于默认(无)私有(k,cell)共享(sim,mesh)
对于(i=0;incells;i++){
单元=&(网格->单元[i]);
对于(k=0;knvar;k++){
单元格->U_辅助[k]=单元格->U[k];
cell->U[k]=sim->dt*((cell->w2->fL_星[k]-cell->w4->fR_星[k])/cell->dx+(cell->w3->fL_星[k]-cell->w1->fR_星[k]/cell->dy+(cell->w6->fL_星[k]-cell->w5->fR_星[k])/cell->dz);
}            
}
}
使用
cell
指向Esstructure
mesh
中单元格数组的指针。我想将它与OpenACC并行

结构
sim
仅包括标量,但结构
mesh
包括1D数组
cell
wall

struct\u网格_{
int ncells;
t_细胞*细胞;
t_墙*墙;
//以及此函数中未使用的其他变量。。。
};
其中结构
单元
定义为:

struct\u单元_{
双dx,dy,dz;
双*U,*U_辅助;
墙*w1、*w2、*w3、*w4、*w5、*w6;
//以及此函数中未使用的其他变量。。。
};
请注意,
*U、*U_aux
是小的1D数组,但
*w1、*w2、*w3、*w4、*w5、*w6
是指向数组
墙的指针:

struct\u墙_{
双星*fR_星,*fL_星;
//以及此函数中未使用的其他变量。。。
};
其中
fR_星
fL_星
是小的一维阵列

?我应该如何定义OpenACC pragma并管理内存

提前谢谢

[编辑]

在下面所附的脚本中,显示了结构的创建和分配,以及在感兴趣的循环中使用的指针。守则的大部分部分已被省略,只保留了问题中提到的部分:

//省略了宏
////////////////////////////////////////////////////
//////////////S T R U C T U R E S///////////////
////////////////////////////////////////////////////
类型定义结构t_节点t_节点;
类型定义结构t_单元t_单元;
typedef struct_wall_uu_wall;
typedef struct_mesh_u_mesh;
typedef struct_sim__sim;
结构t_节点_{
int-id;
双x,y;
};
结构t_单元_{
int-id;
int l,m;
double*U;//单元格值变量数组
双dx,dy;
双xc,yc;
int n1、n2、n3、n4;
int w1_id、w2_id、w3_id、w4_id;
t_wall*w1,*w2,*w3,*w4;//指向网格的指针->墙
};
结构t_墙_{
int-id;
双*fR_星,*fL_星;//每面墙的左右通量阵列(与U相同的尺寸)
内部单元id,单元id;
t_cell*cellR,*cellL;//指向墙的左右单元格的指针(网格->单元格)
双nx,纽约;
};
结构t_网格_{
int xcells,ycells;
双dx,dy;
int ncells;//单元格数
int nwalls;//墙的数量
内nnodes;
t_cell*cell;//单元结构数组
t_wall*wall;//墙结构数组
t_node*node;//节点结构数组
t_sim*sim;
};
结构t_sim_{
双dt,t,CFL;
双tf,tVolc;
内部rk_台阶;
整数阶;
int nvar;//变量的数量(U的维度、fR_星、fL_星…)
};
////////////////////////////////////////////////////
//////F U N C T I O N D F I T I O N//////
////////////////////////////////////////////////////
int create_mesh(t_mesh*mesh,t_sim*sim);
无效更新单元1(t_网格*网格,t_sim*sim);
////////////////////////////////////////////////////
//////P R E-P R O C.F U N C T I O N S///////
////////////////////////////////////////////////////
int创建网格(t网格*网格,t网格*sim){
int i,l,m,k,aux,p;
int xcells,ycells;
t_细胞*细胞;
t_墙*墙;
t_节点*节点;
内半学者;
mesh->sim=sim;
//细胞
xcells=网格->xcells;
Y细胞=网格->Y细胞;
网格->ncells=xcells*ccells;
网格->单元=(t_单元*)malloc(网格->ncells*大小(t_单元));
单元=网格->单元;
//墙
网格->nwalls=2*网格->ncells+xcells+mesh->Y网格;
网格->墙=(t_墙*)malloc(网格->nwalls*尺寸(t_墙));
墙=网格->墙;
对于(k=0;knwalls;k++){
墙[k].id=k;
墙[k].fR_星=(双*)malloc(sim->nvar*sizeof(双));
墙[k].fL_星=(双*)malloc(sim->nvar*大小(双));
}
//单元的墙和节点
对于(m=0;mwall
单元[k].w3=&(网格->墙[cell[k].w3_id]);//墙
// ...
// ...
}
}
//墙相邻细胞的分配
对于(m=0;mcellR=&(单元[k]);
单元[k].w4->cellR=&(单元[k]);
单元格[k].w2->cellL=&(单元格[k]);
单元格[k].w3->cellL=&(单元格[k]);
//...
//其他特殊情况省略
//...
}
}
//单元和墙中变量“U”数组的分配
对于(k=0;kncells;k++){
网格->单元[k].U=(双*)malloc(sim->nvar*sizeof(双));
}
返回1;
}
void update_cellK1(t_mesh*mesh,t_sim*sim){
int i,k;
t_细胞*细胞;
#pragma omp parallel用于默认(无)私有(k,单元)共享(sim,网格)
对于(i=0;incells;i++){
单元=&(网格->单元[i]);
对于(k=0;knvar;k++){
cell->U[k]-=sim->dt*((cell->w2->fL_星[k]-cell->w4->fR_星[k])/cell->dx+(cell->w3->fL_星[k]-cell->w1->fR_星[k])/cell->dy);
}
}   
}
////////////////////////////////////////////////////
////////////////////我是伊恩///////////////////////
////////////////////////////////////////////////////
int main(int argc,char*argv[]){
int i,j,k,p;
t_网格*网格;
t_sim*sim;
双tf,t;
int nIt;
双时间交流;
omp_设置_数量_线程(n线程);
//Mesh和sim分配
网格=(t_网格*)malloc(sizeof(t_网格));
sim=(t_sim*)malloc(sizeof(t_sim));
/
//macros omitted
#include <stdlib.h>
#include <stdio.h>

#ifdef _OPENACC
#include <openacc.h>
#endif

////////////////////////////////////////////////////
//////////////  S T R U C T U R E S  ///////////////
////////////////////////////////////////////////////

typedef struct t_node_ t_node;
typedef struct t_cell_ t_cell;
typedef struct t_wall_ t_wall;
typedef struct t_mesh_ t_mesh;
typedef struct t_sim_ t_sim;

struct t_node_{
    int id;
    double x,y;

};

struct t_cell_{
    int id;
    int l,m;
    double *U;  //array of cell-valued variables
    double dx,dy;
    double xc,yc;
    int n1,n2,n3,n4;
    int w1_id,w2_id,w3_id,w4_id;
    t_wall *w1, *w2, *w3, *w4; //pointers to mesh->wall
};

struct t_wall_{
    int id;
    double *fR_star,*fL_star; //array of left and right fluxes at each wall (same dimension than U)
    int cellR_id, cellL_id;
    t_cell *cellR, *cellL; //pointers to the right and left cells of the wall (mesh->cell)
    double nx, ny;

};

struct t_mesh_{
    int xcells, ycells;
      double dx, dy;
    int ncells; //number of cells
    int nwalls; //number of walls
    int nnodes;
    t_cell *cell; //array of cell structures
    t_wall *wall; //array of wall structures
    t_node *node; //array of node structures
    t_sim *sim;
};

struct t_sim_{
    double dt,t,CFL;
    double tf, tVolc;
    int rk_steps;
    int order;
    int nvar; //number of variables (dimension of U, fR_star, fL_star...)

};


////////////////////////////////////////////////////
//////  F U N C T I O N   D E F I N I T I O N //////
////////////////////////////////////////////////////


int create_mesh(t_mesh *mesh,t_sim *sim);
void update_cellK1(t_mesh *mesh, t_sim *sim);


////////////////////////////////////////////////////
//////  P R E - P R O C.   F U N C T I O N S ///////
////////////////////////////////////////////////////

int create_mesh(t_mesh *mesh, t_sim *sim){
    int i,l,m,k,aux,p;
    int xcells,ycells;
    t_cell *cell;
    t_wall *wall;
    t_node *node;
    int semiSt;

    mesh->sim=sim;

    //Cells
    xcells=mesh->xcells;
    ycells=mesh->ycells;
    mesh->ncells=xcells*ycells;
    mesh->cell=(t_cell*)malloc(mesh->ncells*sizeof(t_cell));
    cell=mesh->cell;

    //Walls
    mesh->nwalls=2*mesh->ncells+xcells+mesh->ycells;
    mesh->wall=(t_wall*)malloc(mesh->nwalls*sizeof(t_wall));

#ifdef _OPENACC
    acc_attach((void**)&mesh->sim);
#pragma acc update device(mesh->ncells,mesh->nwalls)
#pragma acc enter data create(mesh->cell[:mesh->ncells],mesh->wall[:mesh->nwalls])
#endif

    wall=mesh->wall;
    for(k=0;k<mesh->nwalls;k++){
        wall[k].id=k;
        wall[k].fR_star=(double*)malloc(sim->nvar*sizeof(double));
        wall[k].fL_star=(double*)malloc(sim->nvar*sizeof(double));
#pragma acc enter data create(wall[k].fR_star[:sim->nvar], wall[k].fL_star[:sim->nvar])
    }

    //Walls and nodes of the cells
    for(m=0;m<ycells-1;m++){
        for(l=0;l<xcells-1;l++){

            k=xcells*m+l;
            cell[k].id=k;
            cell[k].l=l;
            cell[k].m=m;

            cell[k].w1_id=2*(k)+m;
            // ...

            cell[k].w1=&(mesh->wall[cell[k].w1_id]);  // <------- cells' walls used in function "update_cellK1()" are pointers to mesh->wall
            cell[k].w2=&(mesh->wall[cell[k].w2_id]);  // <------- cells' walls used in function "update_cellK1()" are pointers to mesh->wall
            cell[k].w3=&(mesh->wall[cell[k].w3_id]);  // <------- cells' walls used in function "update_cellK1()" are pointers to mesh->wall
            cell[k].w4=&(mesh->wall[cell[k].w4_id]);  // <------- cells' walls used in function "update_cellK1()" are pointers to mesh->wall
                  // ...
                    // ...
#ifdef _OPENACC
#pragma acc update device(cell[k:1])
            acc_attach((void**)&cell[k].w1);
            acc_attach((void**)&cell[k].w2);
            acc_attach((void**)&cell[k].w3);
            acc_attach((void**)&cell[k].w4);
#endif
        }
    }

    //Assigment of wall's neighbour cells
    for(m=0;m<ycells;m++){
        for(l=0;l<xcells;l++){

            k=xcells*m+l;
            cell[k].w1->cellR_id=cell[k].id;
                  // ...

            cell[k].w1->cellR=&(cell[k]);
            cell[k].w4->cellR=&(cell[k]);
            cell[k].w2->cellL=&(cell[k]);
            cell[k].w3->cellL=&(cell[k]);

            //...
                  //other special cases omitted
                  //...
#ifdef _OPENACC
#pragma acc update device(cell[k].w1->cellR_id)
            acc_attach((void**)&cell[k].w1->cellR);
            acc_attach((void**)&cell[k].w4->cellR);
            acc_attach((void**)&cell[k].w2->cellL);
            acc_attach((void**)&cell[k].w3->cellL);
#endif

        }
    }

    //Allocation of arrays of variables "U" in cells and walls
    for(k=0;k<mesh->ncells;k++){
        mesh->cell[k].U    =(double*)malloc(sim->nvar*sizeof(double));
#pragma acc enter data create(mesh->cell[k].U[:sim->nvar])
    }

    return 1;
}


void update_cellK1(t_mesh *mesh, t_sim *sim){
    int i,k;
    t_cell *cell;
#pragma acc parallel loop present(mesh,sim) private(cell)
    for(i=0;i<mesh->ncells;i++){
        cell=&(mesh->cell[i]);
        for(k=0;k<sim->nvar;k++){
            cell->U[k]-=sim->dt*((cell->w2->fL_star[k]-cell->w4->fR_star[k])/cell->dx + (cell->w3->fL_star[k]-cell->w1->fR_star[k])/cell->dy);
        }
    }
}


////////////////////////////////////////////////////
//////////////////// M A I N ///////////////////////
////////////////////////////////////////////////////

int main(int argc, char * argv[]){

    int i, j, k, p;
    t_mesh *mesh;
    t_sim *sim;
    double tf,t;
    int nIt;
    double timeac;

    //Mesh and sim allocation
    mesh=(t_mesh*)malloc(sizeof(t_mesh));
    sim =(t_sim*)malloc(sizeof(t_sim));


    ////////////////////////////////////////////////////
    ////////////// P R E - P R O C E S S ///////////////
    ////////////////////////////////////////////////////

    //...
    //variable initialization and file reading omitted
    //cell->dx= ...
    //cell->dy= ...
    //...
#pragma acc enter data copyin(mesh[:1]) create(sim[:1])

    create_mesh(mesh,sim);
//    update_initial(mesh); //this function (omitted) assings the initial values of cell[k].U[0] ... cell[k].U[4]

    ////////////////////////////////////////////////////
    ////////////// C A L C U L A T I O N ///////////////
    ////////////////////////////////////////////////////
    tf=sim->tf;
    sim->t=0.0;
    t=0.0;
//    while(t<tf){
//        compute_fluxes(mesh,sim); //this function (omitted) computes *fR_star,*fL_star of walls (line 32), which are then used in "update_cellK1()"
//        update_dt(mesh,sim);      //this function (omitted) computes sim->dt
        update_cellK1(mesh,sim);
//        t+=sim->dt; //Time updated
//        sim->t=t;
//    }

    return 1;

}