Вычислительно эффективные трехмерные массивы в 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, ... Он также описывает макеты данных для хранения точек вместе в памяти.