除了使用经过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
答案 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分而不是在你需要的时候重新计算它们会更快,但我不会打赌。
您也可能根本不需要存储多维数据集限制!