提高3d阵列的性能

时间:2014-02-08 08:35:40

标签: c++ performance bigdata

我尝试循环通过大型3D结构阵列,它的工作速度非常慢。 然后我使用1D阵列而不是3D,但没有成功。

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

struct cellStruct
{
    double v1;
    // more variables here
    double v15;
    double v16;
    double v17;
    double v18;
};

请查看两种使用的方法。

  1. 3D数组

    #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;
            }
    
  2. 1D数组

    #define cell(i,j,k) (cells[(i)*Ny*Nz + (j)*Ny + (k)])
    cellStruct *cells = new cellStruct [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(i,j,k+1).v1 = cell(i,j+1,k-1).v2 * cell(i+1,Ny-1,k+1).v5;
            }
    
  3. 在案例2中,程序运行得更慢。 我怎样才能改进使用大型3D阵列的方法? 使用浮点变量可以将计算速度提高两倍,但我想要更准确。 也许最好使用带有变量指针的结构,如下所示?

    struct cells
    {
        double ***v1;
        // ...
        double ***v15;
        double ***v16;
        double ***v17;
        double ***v18;
    };
    

2 个答案:

答案 0 :(得分:0)

好500 ^ 3是相当大的 - &gt; 125M细胞

  • 所以静态分配是不可能的
  • 每个双数是8Byte所以对于每个双内部8B x 125M = 1G字节(在这种情况下G是1000 ^ 3而不是1024 ^ 3 !!!)
  • 对于单元格内的每个双变量,大约为1GB
  • 所以定义什么意味着n [GB]数据处理的运行缓慢?

你只能这样做:

1.rewrite计算更有效

  • 因此计算出的数据至少符合L1缓存
  • 这意味着以块的形式计算所有内容
  • 当然,如果你没有重复使用细胞,那么你就没有什么可以改进了

2.使用多线程

  • 尝试并行化您的计算
  • 但是你的数据非常庞大,所以这种方法甚至可以减慢速度,所以要小心!!!
  • 当你的数据不适合Caches内部时,那么你的计算能力就像是更强大的386机器!!!

3.打包输入数据

  • 最适合您的选择是一些单元格打包算法
  • 他们是否是Voxel?
  • 所以相邻的细胞应该相似(区域内)
  • 我强烈推荐RLE(行程编码)
  • 对于这种数据来说速度非常快且非常有效(至少对于我假设您使用的数据类型而言)
  • 如果您的数据不适合RLE,则将细胞分成区域并使用DCT / iDCT(如jpg压缩)
  • 打包/解包数据应大大增加您的计算时间
  • 因为打包后你的数据集可能会非常小,现在

答案 1 :(得分:0)

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

我几乎肯定你必须将三重间接指针转换为一维数组,以使数组结构的思想有效。

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

由于您的计算仅使用v1v2v5,因此最好禁用缓存所有其他变量。使用struct-of-arrays布局为v1v2v3等分配不同的内存区域 - 所以你不要强制缓存加载这些无用的{{1 }},v3v4,...

一些语法调整:

v6