如何优化&#39; for循环&#39;用于3d complex <double>数组以提高C ++的速度

时间:2015-07-23 01:52:50

标签: c++ arrays matlab

此代码中的所有数组都是此代码中的复杂类型,此for循环的运行时间约为1分钟。 Ktemp是一个大小为141 * 1202 * 141的阵列。任何人都可以帮我优化这段代码并节省运行时间吗?

 complex<double> ***P1;
        P1 = new complex<double>**[141];
        for (i = 0; i < num_y; i++)
        {
            P1[i] = new complex<double> *[1202];
            for (j = 0; j < tsize; j++)
            {
                P1[i][j] = new complex<double>[141];
            }
        }

        for (int zz = 1; zz < 20; zz++)//in z direction
        {
            for (i = 0; i < 141; i++)
            {
                for (j = 0; j < 1202; j++) 
                {
                    for (k = 0; k < 141; k++)
                    {   
                        if (Ktemp[i][j][k].real() <= 0)
                        {
                            P1[i][j][k] = 0;  
                        }
                        else
                        {
                            P1[i][j][k] = excit_pfft[i][j][k] * expn[i][j][k];
                        }
                    }
                }
            }
            excit_pfft = P1;    
        }

我的第二个问题是关于重写matlab函数&fffhift&#39;用C ++。我已经完成了代码,但似乎效率不高。任何人都可以帮我重写这段代码吗?我的代码附在下面:

complex<double> ***fftw_shift(complex<double> ***te, int a, int b, int c)
{
    complex<double> ***tempa;
    tempa = new complex<double> **[a];
    for (i = 0; i < a; i++)
    {
        tempa[i] = new complex<double> *[b];
        for (j = 0; j < b; j++)
        {
            tempa[i][j] = new complex<double>[c];
        }
    }
    /*for the row*/
    if (c % 2 == 1)
    {
        for (i = 0; i < a; i++)
        {
            for (j = 0; j < b; j++)
            {
                for (k = 0; k < c / 2; k++)
                {
                    tempa[i][j][k] = te[i][j][k + c / 2 + 1];
                    tempa[i][j][k + c / 2] = te[i][j][k];
                    tempa[i][j][c - 1] = te[i][j][c / 2];
                }
            }
        }
    }
    else
    {
        for (i = 0; i < a; i++)
        {
            for (j = 0; j < b; j++)
            {
                for (k = 0; k < c / 2; k++)
                {
                    tempa[i][j][k] = te[i][j][k + c / 2];
                    tempa[i][j][k + c / 2] = te[i][j][k];
                }
            }
        }
    }


    for (i = 0; i < a; i++)
    {
        for (j = 0; j < b; j++)
        {
            for (k = 0; k < c; k++)
            {
                te[i][j][k] = tempa[i][j][k];
            }
        }
    }


    /*for the column*/
    if (b % 2 == 1)
    {
        for (i = 0; i < a; i++)
        {
            for (j = 0; j < b / 2; j++)
            {
                for (k = 0; k < c; k++)
                {
                    tempa[i][j][k] = te[i][j + b / 2 + 1][k];
                    tempa[i][j + b / 2][k] = te[i][j][k];
                    tempa[i][b - 1][k] = te[i][b / 2][k];
                }
            }
        }
    }
    else
    {
        for (i = 0; i < a; i++)
        {
            for (j = 0; j < b / 2; j++)
            {
                for (k = 0; k < c; k++)
                {
                    tempa[i][j][k] = te[i][j + b / 2][k];
                    tempa[i][j + b / 2][k] = te[i][j][k];
                }
            }
        }
    }

    for (i = 0; i < a; i++)
    {
        for (j = 0; j < b; j++)
        {
            for (k = 0; k < c; k++)
            {
                te[i][j][k] = tempa[i][j][k];
            }
        }
    }

    /*for the third dimension*/
    if (a % 2 == 1)
    {

        for (i = 0; i < a / 2; i++)
        {
            for (j = 0; j < b; j++)
            {
                for (k = 0; k < c; k++)
                {
                    tempa[i][j][k] = te[i + a / 2 + 1][j][k];
                    tempa[i + a / 2][j][k] = te[i][j][k];
                    tempa[a - 1][j][k] = te[a / 2][j][k];
                }
            }
        }
    }
    else
    {
        for (i = 0; i < a / 2; i++)
        {
            for (j = 0; j < b; j++)
            {
                for (k = 0; k < c; k++)
                {
                    tempa[i][j][k] = te[i + a / 2][j][k];
                    tempa[i + a / 2][j][k] = te[i][j][k];

                }
            }
        }
    }

    for (i = 0; i < a; i++)
    {
        for (j = 0; j < b; j++)
        {
            for (k = 0; k < c; k++)
            {
                te[i][j][k] = tempa[i][j][k];
            }
        }
    }

    return (te);
}

2 个答案:

答案 0 :(得分:0)

首先(可能会给你带来很大的性能提升),如果你事先知道数组的大小并且只是在堆栈中分配它们,那就摆脱指针数组:

complex<double> P1[141][1202][141];

而不是:

complex<double> ***P1;
P1 = new complex<double>**[141];
for (i = 0; i < num_y; i++)
{
    P1[i] = new complex<double> *[1202];
    for (j = 0; j < tsize; j++)
    {
        P1[i][j] = new complex<double>[141];
    }
}

由于我不确切知道这是做什么的,所以我假设:

    for (int zz = 1; zz < 20; zz++)//in z direction
    {
        for (i = 0; i < 141; i++)
        {
            for (j = 0; j < 1202; j++) 
            {
                for (k = 0; k < 141; k++)
                {   
                    if (Ktemp[i][j][k].real() <= 0)
                    {
                        P1[i][j][k] = 0;  
                    }
                    else
                    {
                        P1[i][j][k] = excit_pfft[i][j][k] * expn[i][j][k];
                    }
                }
            }
        }
        excit_pfft = P1;    
    }

可以成为这个:

    for (int zz = 1; zz < 20; zz++)//in z direction
    {
        for (i = 0; i < 141; i++)
        {
            for (j = 0; j < 1202; j++) 
            {
                for (k = 0; k < 141; k++)
                {   
                    if (Ktemp[i][j][k].real() <= 0)
                    {
                        P1[i][j][k] = 0;  
                    }
                    else
                    {
                        P1[i][j][k] = P1[i][j][k] * expn[i][j][k];
                    }
                }
            }
        }   
    }

如果不能做到这一点,我需要更广泛的代码来分析excit_pfft等。

你可以拥有的巨大性能提升是使用工作线程并运行最后一个代码多线程。

我们的第二个问题也是如此,工作者线程应该这样做。

编辑: 然而,第二,堆栈无法处理那么多变量。 我建议改为使用vector<vector<vector<complex<double> > > >

答案 1 :(得分:0)

由于你反复乘以expn中的值(即计算指数),你可以使用pow函数更有效地做到这一点并摆脱zz循环:

for (i = 0; i < 141; i++)
{
    for (j = 0; j < 1202; j++) 
    {
        for (k = 0; k < 141; k++)
        {   
            if (Ktemp[i][j][k].real() <= 0)
            {
                excit_pfft[i][j][k] = 0;  
            }
            else
            {
                excit_pfft[i][j][k] = excit_pfft[i][j][k] * pow(expn[i][j][k], 20);
            }
        }
    }
}

您的代码似乎也有内存泄漏,因为您将P1分配给excit_pfft,但从不释放先前的excit_pfft内容。一旦摆脱了外循环,就不需要在任何情况下都拥有P1临时数组。

我不确定复杂的pow()函数的内部结构,但是你可以通过将它转换为极坐标(角度+距离标量),然后乘以几何来计算复数的(标量)指数。通过电源的角度和提高电源的距离,然后转换回来。所以它比重复乘法快得多。