рассчитать индекс массива из указателей - PullRequest
2 голосов
/ 20 сентября 2009

Я и некоторые коллеги работаем над игрой (Rigs ofRods) и пытаемся интегрировать OpenCL для расчета физики. В то же время мы пытаемся провести необходимую очистку наших структур данных. Думаю, я должен сказать, что мы пытаемся очистить наши структуры данных и помнить о требованиях OpenCL.

Одной из проблем использования open CL является невозможность использования указателей, поскольку пространство памяти отличается. Из того, что я мало знаю об OpenCL, копирует все данные в графический процессор, затем выполняет вычисления, значения указателей будут скопированы, но адрес не будет соответствовать ожидаемому адресу.

Данные, о которых идет речь, централизованы в массиве, когда объектам нужны эти данные, они используют указатели на нужный ему объект или сохраняют индекс массива.

Одним из решений для учета OpenCL является использование индекса массива вместо указателей. Это приводит к жесткой связи, которая может привести к головной боли в дальнейшем. В качестве решения у меня возникла идея расчета индекса массива на основе адреса начала и адреса текущего. Это, конечно, будет работать только с непрерывным массивом.

Я написал пример приложения, чтобы протестировать это, и оно работало просто отлично, некоторые люди также проверяли его на разных платформах.

#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;
}

Я обеспокоен тем, что это скорее клудж, чем бонифицированный раствор Я знаю, что это не будет работать без непрерывной памяти.

В основном мои вопросы таковы:
Какие были бы подводные камни для использования этого подхода в известной непрерывной памяти?
Как вы могли бы сказать, что это было непрерывно?
Какие подходы использовали люди, когда имели дело с этим типом проблемы?

Спасибо, и мои извинения, если форматирование выключено, я впервые задаю вопрос.

Ответы [ 3 ]

12 голосов
/ 20 сентября 2009

Это должно дать вам индекс pointer относительно base:

pointer - base

Да, это так просто. =]

Используйте ptrdiff_t для переноса результата.

3 голосов
/ 21 сентября 2009

Хотя простое вычитание указателей работает, рекомендуется использовать std::distance. Это также будет работать для типов итераторов, которые не являются указателями, и могут быть перегружены для пользовательских типов. Результат для указателей будет ptrdiff_t.

1 голос
/ 30 января 2014
#define ARRAY_INDEX_FROM_ADDR(base, addr, type) \
(((uintptr_t)(addr)-(uintptr_t)(base))/sizeof(type))

Если не используется C99, используйте unsigned long long вместо uintptr_t

...