我在C中有以下循环,我试图从其中删除if语句,这样就不会在每次迭代中检查它们。然而,我正在努力做到这一点。有没有人有什么建议可以让我把它们弄出来?
for(ix=0;ix<Nx;ix++) {
for(iy=0;iy<Ny;iy++) {
if (ix==0) {
pudx = (u[1][iy] + u[Nx-1][iy] - 2.0*u[0][iy])*(calc1);
} else if (ix==Nx-1) {
pudx = (u[0][iy] + u[Nx-2][iy] - 2.0*u[Nx-1][iy])*(calc1);
} else {
pudx = (u[ix+1][iy] + u[ix-1][iy] - 2.0*u[ix][iy])*(calc1);
}
if (iy==0) {
pudy = (u[ix][1] + u[ix][Ny-1] - 2.0*u[ix][0])*(calc2);
} else if (iy==Ny-1) {
pudy = (u[ix][0] + u[ix][Ny-2] - 2.0*u[ix][Ny-1])*(calc2);
} else {
pudy = (u[ix][iy+1] + u[ix][iy-1] - 2.0*u[ix][iy])*(calc2);
}
u_new[ix][iy] = 2.0*u[ix][iy] - u_old[ix][iy] + calc*(pudx+pudy);
}
}发布于 2017-11-08 08:17:29
for(ix=0;ix<Nx;ix++) {
for(iy=0;iy<Ny;iy++) {
pudx = (u[(ix+1)%Nx][iy] + u[(Nx+ix-1)%Nx][iy] - 2.0*u[ix][iy])*(calc1);
pudy = (u[ix][(iy+1)%Ny] + u[ix][(Ny+iy-1)%Ny] - 2.0*u[ix][iy])*(calc2);
u_new[ix][iy] = 2.0*u[ix][iy] - u_old[ix][iy] + calc*(pudx+pudy);
}
}这不是优化。它只是按照您的要求删除了if条件。
发布于 2017-11-08 09:26:39
这里有一个简单的解决方案:将if内容从循环中去掉,并使它们更明确。它更长,但它为你节省了潜在的耗时的分支和模除计算。我使用预处理器宏来保持工作的整洁,并减少复制-粘贴错误的机会。宏应该本地化到相关的代码,否则像calc1和u_old这样的变量会导致编译错误。基本上,你可以用下面的代码替换你的循环:
#define PUDX0 ((u[1][iy] + u[Nx-1][iy] - 2.0*u[0][iy])*(calc1))
#define PUDX ((u[ix+1][iy] + u[ix-1][iy] - 2.0*u[ix][iy])*(calc1))
#define PUDXN ((u[0][iy] + u[Nx-2][iy] - 2.0*u[Nx-1][iy])*(calc1))
#define PUDY0 ((u[ix][1] + u[ix][Ny-1] - 2.0*u[ix][0])*(calc2))
#define PUDY ((u[ix][iy+1] + u[ix][iy-1] - 2.0*u[ix][iy])*(calc2))
#define PUDYN ((u[ix][0] + u[ix][Ny-2] - 2.0*u[ix][Ny-1])*(calc2))
#define UNEW(x, y, pudx, pudy) u_new[x][y] = 2.0*u[x][y] - u_old[x][y] + calc*(pudx+pudy)
// ix = 0, iy = [0..Ny-1]
UNEW(0, 0, PUDX0, PUDY0);
for (iy=1; iy < Ny-1; iy++) {
UNEW(0, iy, PUDX0, PUDY);
}
UNEW(0, iy, PUDX0, PUDYN);
// ix = [1..Nx-1], iy = Ny-1
for (ix=1; ix < Nx-1; ix++) {
UNEW(ix, iy, PUDX, PUDYN);
}
UNEW(ix, iy, PUDXN, PUDYN);
// ix = Nx-1, iy = [0..Ny-2]
UNEW(ix, 0, PUDXN, PUDY0);
for (iy=1; iy < Ny-1; iy++) {
UNEW(ix, iy, PUDXN, PUDY);
}
// ix = [1..Nx-2], iy = 0
for (ix=1; ix < Nx-1; ix++) {
UNEW(ix, 0, PUDX, PUDY0);
}
// ix = [1..Nx-2], iy = [1..Ny-2]
for (ix=1; ix < Nx-1; ix++) {
for (iy=1; iy < Ny-1; iy++) {
UNEW(ix, iy, PUDX, PUDY);
}
}
#undef UNEW
#undef PUDYN
#undef PUDY
#undef PUDY0
#undef PUDXN
#undef PUDX
#undef PUDX0然而,这显然是为了让计算机处理,而不是供人阅读和稍后修改。宏和注释也是为了帮助人类在以后需要更改时提供帮助。除非原始代码中存在严重的性能问题,否则我个人倾向于使用带有分支语句的原始循环。它可能比较慢,但如果需要的话,调试起来要容易得多!
发布于 2017-11-08 09:38:50
我重写了“前言,主循环,后记”的语义。
void update_u_new(double **u_new, double **u, double **u_old, int ix, int iy, double calc, double pudx, double pudy)
{
u_new[ix][iy] = 2.0*u[ix][iy] - u_old[ix][iy] + calc*(pudx+pudy);
}
//iterates iy=1 to Ny-1
void main_loop_iy(double **u, double **u_new, double **u_old, int ix, int Ny, double pudx, double calc2, double calc)
{
int iy;
for(iy=1; iy<Ny-1; ++iy)
{
double pudy = (u[ix][iy+1] + u[ix][iy-1] - 2.0*u[ix][iy])*(calc2);
update_u_new(u_new, u, u_old, ix, iy, calc, pudx, pudy);
}
}
void do_iy_given_ux(double **u, double **u_new, double **u_old, double *ux_m1, double *ux, double *ux_p1, int ix, int Ny, double calc1, double calc2, double calc)
{
//prologue iy=0
int iy=0;
double pudx = (ux_p1[iy] + ux_m1[iy] - 2.0*ux[iy])*(calc1);
double pudy = (u[ix][1] + u[ix][Ny-1] - 2.0*u[ix][0])*(calc2);
update_u_new(u_new, u, u_old, ix, iy, calc, pudx, pudy);
//main loop 1 <= iy < Ny-1
main_loop_iy(u, u_new, u_old, ix, Ny, pudx, calc2, calc);
//epilogue, iy = Ny-1
iy = Ny-1;
pudy = (u[ix][0] + u[ix][Ny-2] - 2.0*u[ix][Ny-1])*(calc2);
update_u_new(u_new, u, u_old, ix, iy, calc, pudx, pudy);
}
//assumes ix=0
void do_iy_ix0(double **u, double **u_new, double **u_old, int Nx, int Ny, double calc1, double calc2, double calc)
{
int ix=0;
do_iy_given_ux(u, u_new, u_old, u[Nx-1], u[ix], u[ix+1], ix, Ny, calc1, calc2, calc);
}
//assumes ix=1 to Nx-1
void do_iy_given_ix_main_loop(double **u, double **u_new, double **u_old, int ix, int Ny, double calc1, double calc2, double calc)
{
do_iy_given_ux(u, u_new, u_old, u[ix-1], u[ix], u[ix+1], ix, Ny, calc1, calc2, calc);
}
//assumes ix=Nx-1
void do_iy_ixNm1(double **u, double **u_new, double **u_old, int Nx, int Ny, double calc1, double calc2, double calc)
{
int ix = Nx-1;
do_iy_given_ux(u, u_new, u_old, u[0], u[ix], u[ix-1], ix, Ny, calc1, calc2, calc);
}
int do_it(double **u, double **u_new, double **u_old, int Nx, int Ny, double calc, double calc1, double calc2)
{
int ix = 0;
//prologue ix=0
do_iy_ix0(u, u_new, u_old, Nx, Ny, calc1, calc2, calc);
//main loop on 1 <= ix < Nx-1
for(ix=1; ix<Nx-1; ++ix)
{
do_iy_given_ix_main_loop(u, u_new, u_old, ix, Ny, calc1, calc2, calc);
}
//epilogue on ix = Nx-1
do_iy_ixNm1(u, u_new, u_old, Nx, Ny, calc1, calc2, calc);
return 0;
}https://stackoverflow.com/questions/47169355
复制相似问题