これはグッドプラクティスについての質問です
3D エンジン、物理エンジン、有限要素法、または古典的な分子動力学ソルバーなどで典型的な状況を考えてみましょう: さまざまなタイプのオブジェクト (頂点、エッジ、面、境界のあるソリッド ボリュームなど) があり、それらは相互に架橋されています (例:頂点は、どのエッジがそれに接続されているかを認識しており、その逆も同様です)。そのようなエンジンのパフォーマンスと使用の利便性のためには、そのような接続のネットワークをすばやく閲覧できることが重要です。
問題は、リンクされたオブジェクトを配列内のインデックスで指定するのと、ポインタで指定するのとのどちらがよいかということです。...特にパフォーマンス面で
typedef index_t uint16_t;
class Vertex{
Vec3 pos;
#ifdef BY_POINTER
Edge* edges[nMaxEdgesPerVertex];
Face* faces[nMaxFacesPerVertex];
#else
index_t edges[nMaxEdgesPerVertex];
index_t faces[nMaxFacesPerVertex];
#endif
}
class Edge{
Vec3 direction;
double length;
#ifdef BY_POINTER
Vertex* verts[2];
Faces* faces[nMaxFacesPerEdge];
#else
index_t verts[2];
index_t faces[nMaxFacesPerEdge];
#endif
}
class Face{
Vec3 normal;
double isoVal; // Plane equation: normal.dot(test_point)==isoVal
#ifdef BY_POINTER
Vertex* verts[nMaxVertsPerFace];
Edge* edges[nMaxEdgesPerFace];
#else
index_t verts[nMaxVertsPerFace];
index_t edges[nMaxEdgesPerFace];
#endif
}
#ifndef BY_POINTER
// we can use other datastructure here, such as std:vector or even some HashMap
int nVerts,nEdges,nFaces;
Vertex verts[nMaxVerts];
Edge edges[nMaxEdges];
Vertex faces[nMaxFaces];
#endif
インデックスの利点:
- インデックスを使用すると、32 ビットまたは 64 ビットのポインターの代わりにインデックスに
uint8_t
orを使用すると、メモリ効率が向上します。uint16_t
- index は、いくつかのビットでエンコードされたいくつかの追加情報 (たとえば、エッジの向きに関する情報) を運ぶことができます。
- 配列内のオブジェクトの順序付けは、構造に関する情報を運ぶことができます (たとえば、立方体の頂点は次のように順序付けできます
{0b000,0b001,0b010,0b011,0b100,0b101,0b110,0b111}
)。この情報はポインタには表示されません
ポインターの利点:
- オブジェクトを格納するために配列 (または他のデータ構造) を気にする必要はありません。オブジェクトは、 によってヒープ上に動的に割り当てることができます
new Vertex()
。 - 配列のベースアドレスを追加する必要がないため(?)、高速になる可能性があります (?)。しかし、これはメモリ レイテンシに関してはおそらく無視できる程度です (?)。