Вычислительно эффективные трехмерные массивы в C

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

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

Я думал об использовании octtrees, но я был интересно, знает ли кто-нибудь лучший способ.

3 ответов


Octtrees путь. Разделить массив на 8 октантов:

1 2
3 4

---

5 6
7 8

и затем выложить их в памяти в порядке 1, 2, 3, 4, 5, 6, 7, 8 как выше. Вы повторяете это рекурсивно в пределах каждого Октанта, пока не дойдете до некоторого базового размера, вероятно, около 128 байт или около того (это всего лишь предположение-обязательно профилируйте, чтобы определить оптимальную точку отсечения). Это имеет гораздо, гораздо лучшую согласованность кэша и локальность ссылки, чем наивный макет.


одна альтернатива древовидному методу: используйте порядок Мортона для кодирования данных.

в трех измерениях это выглядит так: возьмите компоненты координат и чередуйте каждый бит двумя нулевыми битами. Здесь показано в двоичном формате: 11111b становится 1001001001b

C-функция для этого выглядит так (показано для ясности и только для 11 бит):

int morton3 (int a)
{
  int result = 0;
  int i;
  for (i=0; i<11; i++)
  {
     // check if the i'th bit is set.
     int bit = a&(1<<i);
     if (bit)
     {
       // if so set the 3*i'th bit in the result:
       result |= 1<<(i*3);
     }
  }
  return result;
}

вы можете использовать эту функцию для объединения ваших позиций следующим образом:

index = morton3 (position.x) + 
        morton3 (position.y)*2 +
        morton3 (position.z)*4;

это превращает ваш трехмерный индекс в одномерный. Лучшая часть: значения, близкие в 3D-пространстве, близки и в 1D-пространстве. Если вы часто получаете доступ к значениям, близким друг к другу, вы также получите очень хорошее ускорение, потому что кодировка порядка Мортона оптимальна с точки зрения местоположения кэша.

для morton3 вам лучше не использовать код выше. Используйте небольшую таблицу, чтобы посмотреть 4 или 8 бит за раз и объединить их вместе.

надеюсь, это поможет, Нильс!--3-->


книги основы многомерных и метрических структур данных может помочь вам решить, какая структура данных является самой быстрой для запросов диапазона: octrees, KD-trees, R-trees, ... Он также описывает макеты данных для хранения точек вместе в памяти.