Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.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
C++ 提高三维阵列的性能_C++_Performance_Bigdata - Fatal编程技术网

C++ 提高三维阵列的性能

C++ 提高三维阵列的性能,c++,performance,bigdata,C++,Performance,Bigdata,我试着在巨大的3D结构阵列中循环,但它运行得太慢了。 然后我用1D数组代替3D数组,但没有成功 我使用下面的结构来描述一个3D网格单元的参数: struct cellStruct { double v1; // more variables here double v15; double v16; double v17; double v18; }; 请看两种常用的方法 三维阵列 #define Nx 500 #define Ny 500 #de

我试着在巨大的3D结构阵列中循环,但它运行得太慢了。 然后我用1D数组代替3D数组,但没有成功

我使用下面的结构来描述一个3D网格单元的参数:

struct cellStruct
{
    double v1;
    // more variables here
    double v15;
    double v16;
    double v17;
    double v18;
};
请看两种常用的方法

  • 三维阵列

    #define Nx 500
    #define Ny 500
    #define Nz 500
    
    cellStruct ***cell;
    cell = new cellStruct **[Nx];
    for(int i=0;i<Nx;i++)
    {
        cell[i]=new cellStruct *[Ny];
        for(int j=0;j<Ny;j++)
            cell[i][j]=new cellStruct [Nz];
    }
    
    for (i = 0; i< Nx; ++i)
        for (j = 0; j< Ny; ++j)
            for (k = 0; k< Nz; ++k)
            {
                // big algorithm that uses array like in string below
                cell[i][j][k+1].v1 = cell[i][j+1][k-1].v2 *
                                     cell[i+1][Ny-1][k+1].v5;
            }
    

    井500^3相当大->125M单元

    • 因此,静态分配是不可能的
    • 每个double都是8字节,因此对于8B x 125M内的每个double,它的值都是1G字节(在本例中,G是1000^3,而不是1024^3!!!)
    • 因此,单元内的每个双变量约为1GB
    • 那么,定义n[GB]数据处理的慢运行时间意味着什么
    您只能执行以下操作:

    1.重写计算以提高效率

    • 所以计算出的数据至少适合一级缓存
    • 这意味着要分块计算所有数据
    • 当然,如果你没有重复使用细胞,那么你没有什么可以改进的
    2.使用多线程

    • 尽量使你的计算并行化
    • 但是你的数据太大了,所以这种方法甚至会减慢速度,所以要小心
    • 当您的数据不适合缓存时,您的计算能力就像更强大的386机器
    3.打包输入数据

    • 对您来说,最好的选择是一些单元格打包算法
    • 它们是不是体素的
    • 因此相邻单元应相似(区域内)
    • 我强烈推荐RLE(运行长度编码)
    • 对于这类数据,它是快速且非常有效的(至少对于我假设您使用的数据)
    • 如果您的数据不适合RLE,则将单元格划分为多个区域,并使用DCT/iDCT(如jpg压缩)
    • 打包/解包数据将大大缩短计算时间
    • 因为打包后的数据集可能会非常非常小

    由于您希望提高缓存效率,因此将结构数组转换为阵列结构将对您有所帮助

    我几乎可以肯定,为了使数组结构更有效,您也必须将三重间接指针转换为一维数组

    struct cellStruct
    {
        double* v1; // you can use std::vector<double> instead of double*
        // more variables here
        double* v15;
        double* v16;
        double* v17;
        double* v18;
    };
    

    如果您的大小都是预处理器定义,那么您最好声明
    cellStruct[Nx][Ny][Nz]
    。另外,请注意,在第一个示例中,您的程序可能会因为(k=0;k)的
    而崩溃。这可能会提高性能。此外,当您的结构单元只包含双精度时,您也可以尝试将其编写为数组,以便
    单元[i][j+1][k-1]。v2
    变成
    单元[i][j+1][k-1][2]
    ,也许这有更大的优化潜力…最近有助于解决类似的性能问题,因此请查看我的答案以获取见解。切换到浮动时,处理数据会减半,因此bullet 3更适合您。另外,指针魔术不会为您带来任何有用的效果
    struct cells
    {
        double ***v1;
        // ...
        double ***v15;
        double ***v16;
        double ***v17;
        double ***v18;
    };
    
    struct cellStruct
    {
        double* v1; // you can use std::vector<double> instead of double*
        // more variables here
        double* v15;
        double* v16;
        double* v17;
        double* v18;
    };
    
    #define CELL_ACCESS(cells,vn,i,j,k) (cells.vn[(i)*Ny*Nz + (j)*Ny + (k)])
    cellStruct cells;
    cells.v1 = new double[Nx*Ny*Nz]; // if you use std::vector, adjust code accordingly
    cells.v2 = new double[Nx*Ny*Nz];
    ...
    for (i = 1; i< Nx-1; ++i)
        for (j = 1; j< Ny-1; ++j)
            for (k = 1; k< Nz-1; ++k)
            {
                CELL_ACCESS(     cells, v1, i,   j,    k+1) =
                    CELL_ACCESS( cells, v2, i,   j+1,  k-1) *
                    CELL_ACCESS( cells, v5, i+1, Ny-1, k+1);
            }