任何快速&生成3D网格的有效方法?

时间:2014-11-25 01:15:08

标签: c++ performance computational-geometry

除了使用经过3“for()”循环的标准方法之外,还有更快更有效的方法来生成3D网格吗?我没有使用VTK,OpenGL,TetGen,CGAL或任何其他复杂的库......只是基本的C ++软件,它是CodeBlocks。我的代码如下所示:

#define Dimension 3
#define N_face 5000
struct Point{ float value[Dimension];};

struct Cube{ Point p1, p2, p3, p4, p5, p6, p7, p8;};

int main()
{
    Cube* Grid = (Cube*) malloc(N_face*sizeof(Cube));
    int m=0;
    /*......*/
    delta = ....
    for(int i=0; i<nx; ++i)
    {
        z = i*delta + ....
        for(int j=0; j<ny; ++j)
        {
            y = j*delta + ....
            for(int k=0; k<nz; ++k)
            {
                x = k*delta + ....
                Grid[m].p1= {{x,       y,       z}};
                Grid[m].p2= {{x+delta, y,       z}};
                Grid[m].p3= {{x,       y+delta, z}};
                Grid[m].p4= {{x+delta, y+delta, z}};
                Grid[m].p5= {{x,       y,       z+delta}};
                Grid[m].p6= {{x+delta, y,       z+delta}};
                Grid[m].p7= {{x,       y+delta, z+delta}};
                Grid[m].p8= {{x+delta, y+delta, z+delta}};
                m++;
            }
        }
    }
    /*......*/
}

在上面的代码中,x, y, z, delta是浮动值,计算这些值是为了将网格大小缩放到某个输入几何。我目前正在使用这个网格来检查网格点和多边形的交叉点(内部/外部)(参考此算法的点内/外多边形[http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf])我已设法完成程序和得到预期的结果,但它需要很长时间来运行它,因为我正在处理数千点。因此,现在我正在努力改进编码.....真的需要你的帮助.... T.T

3 个答案:

答案 0 :(得分:2)

首先,如果你的代码已经运行缓慢了几千点,我预计它会成为一个错误,即使我不能立即看到你的代码有任何问题......

关于优化: 如果必须访问大量元素,有两种方法可以提高性能:内存访问优化和并行性。

第一个是确保您始终以块的形式读/写内存,而不是在远程地址之间跳转。这减少了将新页面加载到缓存中所浪费的时间。 但是:在您的示例中,您已经通过编写Grid[m] = ...; m++;按顺序写入内存,因此这已经是最佳的。

第二种方法是使用SIMD指令:SSE允许您同时写入多个浮点值,从而加快您的过程。

#include <xmmintrin.h>
...
__m128 your_first_four_floats  = _mm_set_ps (a, b, c, d);
__m128 your_second_four_floats = _mm_set_ps (e, f, g, h);
...
_mm_store_ps(((float*)&Grid[m])+0,your_first_four_floats);
_mm_store_ps(((float*)&Grid[m])+4,your_second_four_floats);
...

这是一个非常糟糕的例子,所以请不要认真对待。您可以找到更好的方法来轻松生成您的价值观! 还要确保分配的内存是16字节对齐的(应该是64位代码的默认值,在32位代码中需要使用_aligned_malloc(bytes, 16))。否则你将不得不使用_mm_storeu_ps,这有点慢。

如果你有一个多核CPU(这些天通常是标准的)你也可以使用多个线程来生成值,但为此你需要一些线程库或一个相当新版本的C ++(C ++ 11)并不总是支持。此外,如果内存访问是您的瓶颈,这并不一定能为您带来任何加速。

答案 1 :(得分:1)

内存分配可能很慢 - 除非你需要,否则不要这样做 - 尽量少做:

您的多维数据集包含可在运行时计算的一堆信息,从多维数据集到多维数据集几乎相同。我假设每个Cube中都存储了额外的信息,我将称之为CubeMutableData

我会考虑这样做:

struct CubeMutableData {
  boolean inside;
};

struct Cube {
  Point p1; 
  ..
  CubeMutableData * data;
};

class CubeBuilder {
  //TODO: This needs an appropriate constructor that initializes these
  CubeMutableData * perCubeData;
  float delta;
  public:
  Cube createCube(int i, int j, int k) {
    Cube result;
    float z = i*delta + ....
    float y = j*delta + ....
    float x = k*delta + ....
    result.p1 = Point(x,y,z);
    result.p2 = Point(...);
    ..
    result.data = perCubeData[i+j*nx+k*nx*ny];
  }
}

int main() {

  CubeBuilder cubes(nx,ny,nz, delta, origin);

  // Loop through the cubes and use them.
  // Note that the Cubes geometry is transient, but their data
  // is saved back into the perCubeData member of the CubeBuilder.
  for(int i=0; i<nx; ++i) {
    for(int j=0; j<ny; ++j) {
      for(int k=0; k<nz; ++k) {
        Cube cube = cubes.getCube(i,j,k);
        Point p = cube.getCenter();
        cube.data->inside = geom.contains(p);
      }
    }
  }
}

这比你的例子分配更少的内存,编译器应该能够很好地优化它。

答案 2 :(得分:0)

真正的问题可能不在于网格生成。因为您出于某种目的使用此网格,并且处理时间将主导网格节点生成的时间。所以任何微观优化都没有用。

这就是说,每个节点存储24个值,当3个足够时(X,Y,Z; Delta似乎是常数)。你可以说,预先计算8分而不是在你需要的时候重新计算它们会更快,但我不会打赌。

您也可能根本不需要存储多维数据集限制!