3

私と何人かの仲間がゲーム (Rigs ofRods) に取り組んでおり、物理計算のために OpenCL を統合しようとしています。同時に、データ構造の非常に必要なクリーンアップを実行しようとしています。私たちはデータ構造をクリーンアップし、OpenCL の要件に注意を払っていると言うべきだと思います。

オープン CL を使用する際の問題の 1 つは、メモリ空間が異なるためポインターを使用できないことです。OpenCLについて私が知っていることはほとんどありませんが、すべてのデータをGPUにコピーしてから計算を実行すると、ポインター値がコピーされますが、アドレスは予想されるアドレスに対応しません。

問題のデータは配列に集中されます。オブジェクトがそのデータを必要とする場合、必要なオブジェクトへのポインターを使用するか、配列インデックスを格納します。

OpenCL を説明する 1 つの解決策は、ポインターの代わりに配列インデックスを使用することです。これはハードカップリングにつながり、後で頭痛の種になる可能性があります。解決策として、開始アドレスと現在のアドレスに基づいて配列インデックスを計算するという考えがありました。もちろん、これは連続配列でのみ機能します。

これをテストするためにサンプル アプリを作成しましたが、問題なく動作し、別のプラットフォームでも検証された人もいます。

#include <iostream>

typedef struct beam_t
{
 unsigned int item;
} beam_t;

#define GLOBAL_STATIC_ASSERT(expr, msg)   \
  extern char STATIC_ASSERTION__##msg[1]; \
  extern char STATIC_ASSERTION__##msg[(expr)?1:2]


#ifdef __amd64
typedef unsigned long pointer_int;
#else
typedef unsigned int pointer_int;
#endif
GLOBAL_STATIC_ASSERT(sizeof(pointer_int) == sizeof(pointer_int*), integer_size);
#define MAX_BEAM 5


int main ()
{
 beam_t beams[MAX_BEAM];
 beam_t* beam_start = &beams[0];
 beam_t* beam_ptr = NULL;

 std::cout << "beams: " << &beams << "\n";

 for( pointer_int i = 0; i < MAX_BEAM; ++i )
 {
  beam_ptr = &beams[i];
  pointer_int diff = ((pointer_int)beam_ptr - (pointer_int)beam_start);
  std::cout << "beams[" << i << "]: " << beam_ptr
      << "\t calculated index:" <<  diff / sizeof(beam_t)
      << "\n";
 }
 return 0;
}

これは骨の折れる解決策というよりも、クラッジのようなものではないかと心配しています。これが非連続メモリでは機能しないことは承知しています。

基本的に私の質問は次のとおり
です。既知の連続メモリでこのアプローチを使用する場合の落とし穴は何ですか?
それが連続的であるとどのように判断できますか?
この種の問題に対処するとき、人々はどのようなアプローチをとってきましたか?

ありがとうございます。フォーマットがずれている場合はお詫び申し上げます。質問を投稿するのはこれが初めてです。

4

3 に答える 3

13

pointerこれにより、に対する相対的なインデックスが得られますbase

pointer - base

はい、とても簡単です。=]

ptrdiff_t結果をポータブルに保存するために使用します。

于 2009-09-20T19:09:00.210 に答える
3

ポインタの単純な減算は機能しますが、を使用することをお勧めしますstd::distance。これは、ポインターではないイテレーター型でも機能し、カスタム型でもオーバーロードできます。ポインタの結果は、になりますptrdiff_t

于 2009-09-20T20:26:40.180 に答える
1
#define ARRAY_INDEX_FROM_ADDR(base, addr, type) \
(((uintptr_t)(addr)-(uintptr_t)(base))/sizeof(type))

C99 を使用していない場合は、unsigned long long代わりに使用しますuintptr_t

于 2014-01-30T08:22:42.967 に答える