背景
ゲームエンジン開発では、通常、最適なメモリと計算パフォーマンスのためにデータ指向設計を使用します。Rustでデータ指向設計を実装するにはどうすればよいですか?
パーティクルシステムを例にしましょう。パーティクルシステムで
は、我々は、粒子の多くを有し、各粒子は、等の位置、速度、などのいくつかの属性を有することができるC++における典型的な実装は次のようになり:
struct Particle {
float positionX, positionY, positionZ;
float velocityX, velocityY, velocityZ;
float mass;
// ...
};
struct ParticleSystem {
vector<Particle> particles;
// ...
};
この実装の1つの問題は、パーティクルの属性が相互にインターリーブされていることです。 このメモリレイアウトはキャッシュに適しておらず、SIMD計算には適していません。今、私たちは一つだけの割り当てがあり、各属性が連続してメモリに常駐
struct ParticleAttribute {
size_t size;
size_t alignment;
const char* semantic;
};
struct ParticleSystem {
ParticleSystem(
size_t numParticles,
const ParticleAttribute* attributes,
size_t bufferSize) {
for (size_t i = 0; i < numAttributes; ++i) {
bufferSize += attributes[i].size * numParticles;
// Also add paddings to satisfy the alignment requirements.
}
particleBuffer = malloc(bufferSize);
}
uint8* getAttribute(const char* semantic) {
// Locate the semantic in attributes array.
// Compute the offset to the starting address of that attribute.
}
uint8* particleBuffer;
};
:
は、代わりに、データ指向設計では、我々は以下のコードを記述します。 は、我々は次のコード書くことができ、粒子をシミュレートするには、次の
symplecticEuler(ps.getAttribute("positionX"), ps.getAttribute("velocityX"), dt);
getAttribute
機能は、特定の属性の開始アドレスを取得します。
質問
これをRustで実装する方法を知りたいと思います。
私はまず、ParticleSystem
というクラスを作成します。このクラスは、合計バッファサイズを計算するために数十ParticleAttribute
を受け取り、バッファのメモリを割り当てます。 これはRustセーフコードで実行できると思います。
次のステップは、getAttribute
関数を実装することです。 は、特定の属性の開始アドレスへの参照を返します。 ここにあなたの助けが必要です。 ローアドレスをオフセットで取得し、目的の型(float *など)にキャストし、その生ポインタをRustの可変参照にラップしますか?
また、私はその参照を介して4つの要素を読み込むためにSIMDライブラリを使用する必要があるので、配列への可変参照への生のポインタをラップする必要がありますと思う。 Rustを使用してこれを達成するにはどうすればよいですか?
更新:属性に関する詳細情報を提供してください。 属性の数と詳細情報は実行時に決定されます。 属性の種類はさまざまですが、基本的なもの(f32、f64、ints、...)のみをサポートする必要があると思います。
すぐにお返事ありがとうございます。属性の柔軟性が必要なため、DODを実装するこの複雑な方法に到達しました。通常、詳細な属性情報(すなわち、属性の数および正確な意味)は、アーティストからのものである。言い換えれば、この情報は動的であり、ランタイムの前に決定することはできません。 – TheBusyTypist
@TheBusyTypist:そうです...関連する詳細を含む質問を編集してください。また、 'f32'(' HashMap> 'はかなりうまくいくでしょう)をサポートする必要があるのか、複数のタイプをサポートする必要があるのかを知ることも価値があります。 –
私は 'f64'や' int's(パーティクルIDのような)のような他のプリミティブ型をサポートしなければなりません。あなたが提案したように、別の 'HashMap'で属性をグループ化することは、その型によって有効な解決策になると思います。 – TheBusyTypist